Hi, 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.
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) 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...); sprintf(dest, "%dconstant%...", args1, args...) -> sprintf(dest, "%d", args1); memcpy(dest+X, "constant", 8); sprintf(dest+XX, "%...", args...); 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. I don't have much experience with GCC hacking, but I did put together a prototype to do some of the above, and it does look like you can get very significant speedups. Before I continue with that, has something like this been proposed before? I couldn't find anything relevant in the archives. One small problem I see is that if you replace one of the output handlers for something like %s with register_printf_function, the simplified code won't honor that replacement. Actually, we have that problem with the simplifications we already do, and replacing %s would be a pretty dumb thing to do anyway, so I don't think that's a show stopper. Thoughts? -- Heikki Linnakangas EnterpriseDB http://www.enterprisedb.com