This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Preparsing sprintf format strings


On Monday 08 October 2007 13:50, Heikki Linnakangas wrote:
> While profiling a test case of exporting data from PostgreSQL, I noticed
> that a lot of CPU time was spent in sprintf, formatting timestamps like
> "2007-10-01 12:34". I could speed that up by an order of magnitude by
> replacing the sprintf call with tailored code, but it occurred to me
> that we could do the same in a more generic way in GCC.

It is already done in gcc to some extent: for example, it
replaces printf("message\n") with puts("Message").

It's too far-fetched for my tastes. I think gcc should not do it.
How gcc can know what printf() and puts() mean in *my* libc?

I think such optimizations should be done in glibc.

> The format string is almost always a string literal, so instead of
> parsing it at runtime in glibc sprintf, we can preparse it in gcc. We
> already rewrite two simple cases:
> 
> sprintf(dest, "constant") -> strcpy(dest, "constant")
> sprintf(dest, "%s", ptr) -> strcpy(dest, ptr)

If done in glibc, it can work even for

sprintf(dest, variable_which_happens_to_have_no_percents)
sprintf(dest, fmt, ptr) /* fmt var may be "%s" here */

> To effectively preparse any common format string, I'm proposing that we
> add more rules to rewrite this kind of format strings as well:
> 
> sprintf(dest, "%d", arg1); -> a new function that does the same thing,
> but without the overhead of parsing the format string. Like itoa on some
> platforms. We could inline it as well. That would allow further
> optimizations, if for example the compiler knows that arg1 is within a
> certain range (do we do that kind of optimizations?)
> 
> sprintf(dest, "constant%...", args...) -> memcpy(dest, "constant", 8);
> sprintf(dest+8, "%...", args...);

Just make printf faster instead by implementing it there.

> sprintf(dest, "%dconstant%...", args1, args...) -> sprintf(dest, "%d",
> args1); memcpy(dest+X, "constant", 8); sprintf(dest+XX, "%...", args...);

How do you know that in this place user wants faster, not smaller code?

> If the sprintf and memcpy calls generated in the last two rewrites are
> further simplified, format strings like "%d-%d-%d" wouldn't need to call
> the glibc sprintf at all. The last form of rewrite wouldn't likely be a
> win unless the resulting sprintf-calls can be converted into something
> cheaper, because otherwise we're just introducing more library call
> overhead.

Yes, printing dates and whatnot is very binary->decimal intensive.

In linux kernel, decimal conversion in vsprintf() is optimized
with custom conversion code. x3 faster, and no, it's not written in assembly.
You may port it to glibc.
--
vda


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]