As we saw yesterday, padding can be hard.
Jasmine received a set of tickets all complaining that the file download portion of an ASP .Net application took too long. Users frequently had to wait for up to 15 minutes before their browser finished downloading the output of the web application.
This particular module generated the file by doing a set of Response.Write
s to build the file as part of the HTTP response. This particular line ran 200,000 times in the process of creating the file:
myResponse.Write("P;P#,##0." + new string('0', 2) + "_);;[Red]\\(#,##0." + new string('0', 2) + "\\)\n");
I'm not entirely clear what they're writing out here- it looks like some kind of format template. But the contents don't really matter. The string concatenation operations look like they're handling decimal places- 0.00
. Given that the new string
is hard coded to two zeros, there's no need for string concatenation, they could have just put the 00
right in the output string.
But for fun, let's count the strings that this operation creates, noting that strings are immutable in C#, so each concatenation creates a new string.
First, let's give credit to the literals- C# is smart, and string literals get only one instance created, so we can ignore those. The new string
operation creates two new strings. Then each concatenation creates a new string- four.
That's a total of 6 new string instances, which isn't a lot, but given that if they just did a literal there'd be 0 new string instances, it's still a notable increase. But this line executes in a loop, 200,000 times, meaning we're spamming 1,200,000 string instances in each execution of that loop. And this line is a representative line; the whole loop has many such lines, allowing this code to quite effectively stress test the garbage collector.
Without a single change to the logic, and just switching to string formatting and string builders, Jasmine was able to get this particular file generation down from 15 minutes to closer to a few seconds.