Closed
Bug 213753
Opened 22 years ago
Closed 21 years ago
[ps] Runtime bloat in gfx/src/ps/nsPostScriptObj.cpp from fprintf()s
Categories
(Core :: Printing: Output, defect)
Core
Printing: Output
Tracking
()
RESOLVED
FIXED
People
(Reporter: kherron+mozilla, Assigned: kherron+mozilla)
Details
(Keywords: memory-footprint)
Attachments
(2 files)
92.25 KB,
patch
|
dbaron
:
review+
bzbarsky
:
superreview+
|
Details | Diff | Splinter Review |
2.00 KB,
text/plain
|
Details |
nsPostScriptObj.cpp contains a sequence of over 1300 calls to fprintf() each
printing a one-line string. This contributes around 32k to the runtime code size
on linux (about 45k on solaris) contrasted with using a single fprintf() call.
Assignee | ||
Comment 1•22 years ago
|
||
This patch converts the entire block to a single |fprintf| call. The compiler
concats the individual strings into one big string.
This saves about 32k of text on linux (gcc 3.2):
> size libgfx* nsPost*
text data bss dec hex filename
265206 217300 44 482550 75cf6 libgfxps.so
299447 217328 44 516819 7e2d3 libgfxps.so.old
60862 2032 8 62902 f5b6 nsPostScriptObj.o
92644 2032 8 94684 171dc nsPostScriptObj.o.old
and about 45k on solaris:
> size libgfx* nsPostScriptObj.o*
libgfxps.so: 145320 + 233464 + 64 = 378848
libgfxps.so.old: 190960 + 238440 + 64 = 429464
nsPostScriptObj.o: 91887 + 2688 + 8 = 94583
nsPostScriptObj.o.old: 199262 + 2688 + 8 = 201958
On my fairly wimpy solaris box, it also reduces the time to compile this file
from 8m15s using 120Mb to 0m20s using 20Mb.
Assignee | ||
Comment 2•22 years ago
|
||
Comment on attachment 128443 [details] [diff] [review]
Convert to a single |fprintf| call.
I was asked in IRC how I produced the patch. It was basically three vi s//
operations. From memory:
s/^ fprintf(f, / /
s/); *$//
s/\%\%/\%/g
i.e. fix up the beginning of each line, fix up the end, and un-double the %
characters. A couple of lines had to be cleaned up by hand because they didn't
match the first pattern properly.
The |fprintf| calls in question are all printing constant strings with no
variable values involved. Before making the change I printed a test page to a
file. After making the change I reprinted the page and compared the resulting
PS; there was no difference other than a timestamp which appears at the bottom
of each page.
Attachment #128443 -
Flags: superreview?(bzbarsky)
Attachment #128443 -
Flags: review?(timeless)
![]() |
||
Comment 3•22 years ago
|
||
Comment on attachment 128443 [details] [diff] [review]
Convert to a single |fprintf| call.
sr=bzbarsky; once this has review, let me know and I can land it.
Attachment #128443 -
Flags: superreview?(bzbarsky) → superreview+
Updated•22 years ago
|
Summary: Runtime bloat in gfx/src/ps/nsPostScriptObj.cpp from fprintf()s → [ps] Runtime bloat in gfx/src/ps/nsPostScriptObj.cpp from fprintf()s
At about line 610 you end up with
fprintf(f, "%s", huge_string);
Wouldn't
fputs (huge_string, f);
be faster? There are actually lots of other places where this also
occurs.
Assignee | ||
Comment 5•22 years ago
|
||
I wrote a quickie benchmark that tests four different methods of writing a big
string and got results like the following:
fprintf(f, String) 17400876
fprintf(f, %s, String) 2297751
fputs(String, f) 2482240
fwrite(String, sizeof, sizeof, f) 115029
fprintf(f, String) 15610071
fprintf(f, %s, String) 3248828
fputs(String, f) 2884262
fwrite(String, sizeof, sizeof, f) 154088
fprintf(f, String) 16031274
fprintf(f, %s, String) 2507793
fputs(String, f) 2234064
fwrite(String, sizeof, sizeof, f) 115137
fprintf(f, String) 14915339
fprintf(f, %s, String) 2595806
fputs(String, f) 2410765
fwrite(String, sizeof, sizeof, f) 153214
Those numbers are time in microseconds to do the operation 100,000 times writing
to /dev/null. As you can see there's a big advantage going from
fprintf(f, string)
to
fprintf(f, "%s", string)
and another big advantage going to |fwrite|. |fprintf| vs. |fputs| tends to
favor |fputs| but the results aren't consistent.
That said, this code only runs once per document printed, so optimizing for
speed isn't the first priority. I used fprintf because I felt that
fputs(
[1314 lines]
, f)
was bad style. fwrite is worse in this regard.
Comment on attachment 128443 [details] [diff] [review]
Convert to a single |fprintf| call.
r=dbaron if you do a before-patch and after-patch printing tests, diff the two
resulting postscript files, and make sure they're the same. (I didn't look too
closely. My eyes would glaze over.)
Attachment #128443 -
Flags: review?(timeless) → review+
Assignee | ||
Comment 7•21 years ago
|
||
Clearly, people aren't comfortable that the patch contains no mistakes. So I've
written this perl script to perform the change. You can run it as:
perl ./convert-it nsPostScriptObj.cpp > new-file # Writes to stdout
perl -i.bak ./convert-it nsPostScriptObj.cpp # Update in place
When run as above, the script will convert the block of code to a single
fprintf() call, identical to the patch. Alternately, you can add the switch
"-fwrite":
perl ./convert-it -fwrite nsPostScriptObj.cpp > new-file
In this case it will convert the code to the form:
static const char psBoilerplate[] = {
"/rhc {\n"
" {\n"
" currentfile read {\n"
[etc.]
" /unicodeshow2 { real_unicodeshow_native } bind def\n"
"} bind def\n"
"\n"
};
fwrite(psBoilerplate, 1, sizeof(psBoilerplate) - 1, f);
As noted in a previous comment, fwrite() is faster than fprintf() (though
again, this code only executes once per print job).
Whether using the patch or the perl script, the generated postscript is
identical. The following files were produced by printing the google home page
to a file using various versions of mozilla:
$ ls -l google*
-rw-r--r-- 1 kherron kherron 227780 Sep 20 13:01 google-orig.ps
-rw-r--r-- 1 kherron kherron 227780 Sep 20 13:05 google-patch.ps
-rw-r--r-- 1 kherron kherron 227780 Sep 20 13:12 google-perl-fprintf.ps
-rw-r--r-- 1 kherron kherron 227780 Sep 20 13:17 google-perl-fwrite.ps
$ md5sum google*
45c830db9ed9a39ec4567db4cb871118 google-orig.ps
45c830db9ed9a39ec4567db4cb871118 google-patch.ps
45c830db9ed9a39ec4567db4cb871118 google-perl-fprintf.ps
45c830db9ed9a39ec4567db4cb871118 google-perl-fwrite.ps
Mozilla print jobs normally contain the date/time in the margin; to avoid this
I went into File->Page Setup->Margins, then set the right footer to "blank".
->kjh
Assignee: printing → kjh-5727
Fix checked in to trunk, 2003-09-20 14:27 -0700.
Status: NEW → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
libgfxps.so
Total: -22736 (+0/-22736)
Code: -21040 (+0/-21040)
Data: -1696 (+0/-1696)
-1696 (+0/-1696) R (DATA)
-1696 (+0/-1696) UNDEF:libgfxps.so:R
-20 kCharsetConverterManagerCID
-1676 kFCSCID
-21040 (+0/-21040) T (CODE)
-21040 (+0/-21040) UNDEF:libgfxps.so:T
-8 global constructors keyed to
nsRenderingContextImpl::gBackbuffer
-21032 nsPostScriptObj::begin_document(void)
You need to log in
before you can comment on or make changes to this bug.
Description
•