Skip Menu |

This queue is for tickets about the PDF-API2 CPAN distribution.

Report information
The Basics
Id: 44747
Status: rejected
Priority: 0/
Queue: PDF-API2

People
Owner: Nobody in particular
Requestors: NWELLNHOF [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: [PATCH] Reduce PDF::API2 memory consumption
I'm using PDF:API2 to generate PDFs on the fly on a web server. Recently, I ran into the 32MB memory limit of a shared hosting provider. So I had a look at the memory consumption of PDF::API2. After creating a PDF::API2 object and loading some fonts, memory usage was about 25MB. With the following fixes I managed to reduce that to about 15MB. Most of the savings can be obtained if you only "require" some of the PDF::API2 packages when needed. See the attached patch pdf-api2-require-packages.diff. I could also save about three additional MB by rewriting the code for glyph name initialization. See the attached patch pdf-api2-glyph-names.diff. Note that this patch breaks the function initNameTable in PDF/API2 Util.pm. It doesn't seem to be part of the public API, though, and it isn't used internally.
Subject: pdf-api2-require-packages.diff
diff -urN -x fonts -x 'CJKFont*' -x CMap PDF-API2-0.73/lib/PDF/API2.pm ../htdocs/cgi-bin/lib/PDF/API2.pm --- PDF-API2-0.73/lib/PDF/API2.pm 2008-01-18 01:11:38.000000000 +0100 +++ ../htdocs/cgi-bin/lib/PDF/API2.pm 2009-02-11 15:27:54.000000000 +0100 @@ -53,46 +53,8 @@ use PDF::API2::Util; use PDF::API2::Page; - use PDF::API2::Outlines; - use PDF::API2::NamedDestination; - use PDF::API2::Version; - use PDF::API2::Resource::ExtGState; - use PDF::API2::Resource::Pattern; - use PDF::API2::Resource::Shading; - - use PDF::API2::Resource::Font::CoreFont; - use PDF::API2::Resource::Font::Postscript; - use PDF::API2::Resource::Font::BdFont; - use PDF::API2::Resource::Font::SynFont; - use PDF::API2::Resource::Font::neTrueType; - use PDF::API2::Resource::CIDFont::TrueType; - use PDF::API2::Resource::CIDFont::CJKFont; - use PDF::API2::Resource::UniFont; - - use PDF::API2::Resource::XObject::Image::JPEG; - use PDF::API2::Resource::XObject::Image::TIFF; - use PDF::API2::Resource::XObject::Image::PNM; - use PDF::API2::Resource::XObject::Image::PNG; - use PDF::API2::Resource::XObject::Image::GIF; - use PDF::API2::Resource::XObject::Image::GD; - - use PDF::API2::Resource::XObject::Form::Hybrid; - - use PDF::API2::Resource::XObject::Form::BarCode::int2of5; - use PDF::API2::Resource::XObject::Form::BarCode::codabar; - use PDF::API2::Resource::XObject::Form::BarCode::code128; - use PDF::API2::Resource::XObject::Form::BarCode::code3of9; - use PDF::API2::Resource::XObject::Form::BarCode::ean13; - - use PDF::API2::Resource::ColorSpace::Indexed::ACTFile; - use PDF::API2::Resource::ColorSpace::Indexed::Hue; - use PDF::API2::Resource::ColorSpace::Indexed::WebColor; - - use PDF::API2::Resource::ColorSpace::Separation; - use PDF::API2::Resource::ColorSpace::DeviceN; - use Compress::Zlib; use Math::Trig; @@ -1644,6 +1606,7 @@ sub corefont { my ($self,$name,@opts)=@_; + require PDF::API2::Resource::Font::CoreFont; my $obj=PDF::API2::Resource::Font::CoreFont->new_api($self,$name,@opts); $self->resource('Font',$obj->name,$obj); $self->{pdf}->out_obj($self->{pages}); @@ -1689,6 +1652,7 @@ $opts{$o}=_findFont($opts{$o}); } $psf=_findFont($psf); + require PDF::API2::Resource::Font::Postscript; my $obj=PDF::API2::Resource::Font::Postscript->new_api($self,$psf,%opts); $self->resource('Font',$obj->name,$obj,$self->{reopened}); @@ -1730,6 +1694,7 @@ my ($self,$file,%opts)=@_; $file=_findFont($file); + require PDF::API2::Resource::CIDFont::TrueType; my $obj=PDF::API2::Resource::CIDFont::TrueType->new_api($self,$file,%opts); $self->resource('Font',$obj->name,$obj,$self->{reopened}); @@ -1743,6 +1708,7 @@ my ($self,$file,%opts)=@_; $file=_findFont($file); + require PDF::API2::Resource::Font::neTrueType; my $obj=PDF::API2::Resource::Font::neTrueType->new_api($self,$file,%opts); $self->resource('Font',$obj->name,$obj,$self->{reopened}); @@ -1776,6 +1742,7 @@ sub cjkfont { my ($self,$name,%opts)=@_; + require PDF::API2::Resource::CIDFont::CJKFont; my $obj=PDF::API2::Resource::CIDFont::CJKFont->new_api($self,$name,%opts); $self->resource('Font',$obj->name,$obj,$self->{reopened}); @@ -1821,6 +1788,7 @@ sub synfont { my ($self,@opts)=@_; + require PDF::API2::Resource::Font::SynFont; my $obj=PDF::API2::Resource::Font::SynFont->new_api($self,@opts); $self->resource('Font',$obj->name,$obj,$self->{reopened}); @@ -1845,6 +1813,7 @@ sub bdfont { my ($self,@opts)=@_; + require PDF::API2::Resource::Font::BdFont; my $obj=PDF::API2::Resource::Font::BdFont->new_api($self,@opts); $self->resource('Font',$obj->name,$obj,$self->{reopened}); @@ -1875,6 +1844,7 @@ sub unifont { my ($self,@opts)=@_; + require PDF::API2::Resource::UniFont; my $obj=PDF::API2::Resource::UniFont->new_api($self,@opts); return($obj); @@ -1895,6 +1865,7 @@ sub image_jpeg { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::XObject::Image::JPEG; my $obj=PDF::API2::Resource::XObject::Image::JPEG->new_api($self,$file); $self->resource('XObject',$obj->name,$obj); @@ -1912,6 +1883,7 @@ sub image_tiff { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::XObject::Image::TIFF; my $obj=PDF::API2::Resource::XObject::Image::TIFF->new_api($self,$file); $self->resource('XObject',$obj->name,$obj); @@ -1929,6 +1901,7 @@ sub image_pnm { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::XObject::Image::PNM; my $obj=PDF::API2::Resource::XObject::Image::PNM->new_api($self,$file); $self->resource('XObject',$obj->name,$obj); @@ -1946,6 +1919,7 @@ sub image_png { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::XObject::Image::PNG; my $obj=PDF::API2::Resource::XObject::Image::PNG->new_api($self,$file); $self->resource('XObject',$obj->name,$obj); @@ -1963,6 +1937,7 @@ sub image_gif { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::XObject::Image::GIF; my $obj=PDF::API2::Resource::XObject::Image::GIF->new_api($self,$file); $self->resource('XObject',$obj->name,$obj); @@ -1982,6 +1957,7 @@ sub image_gd { my ($self,$gd,%opts)=@_; + require PDF::API2::Resource::XObject::Image::GD; my $obj=PDF::API2::Resource::XObject::Image::GD->new_api($self,$gd,undef,%opts); $self->resource('XObject',$obj->name,$obj); @@ -2136,6 +2112,7 @@ sub colorspace_act { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::ColorSpace::Indexed::ACTFile; my $obj=PDF::API2::Resource::ColorSpace::Indexed::ACTFile->new_api($self,$file); $self->resource('ColorSpace',$obj->name,$obj); @@ -2159,6 +2136,7 @@ sub colorspace_web { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::ColorSpace::Indexed::WebColor; my $obj=PDF::API2::Resource::ColorSpace::Indexed::WebColor->new_api($self); $self->resource('ColorSpace',$obj->name,$obj); @@ -2182,6 +2160,7 @@ sub colorspace_hue { my ($self,$file,%opts)=@_; + require PDF::API2::Resource::ColorSpace::Indexed::Hue; my $obj=PDF::API2::Resource::ColorSpace::Indexed::Hue->new_api($self); $self->resource('ColorSpace',$obj->name,$obj); @@ -2210,6 +2189,7 @@ sub colorspace_separation { my ($self,$name,@clr)=@_; + require PDF::API2::Resource::ColorSpace::Separation; my $obj=PDF::API2::Resource::ColorSpace::Separation->new_api($self,$name,@clr); $self->resource('ColorSpace',$obj->name,$obj); @@ -2244,6 +2224,7 @@ my ($self,$clrs,$samples)=@_; $samples||=2; + require PDF::API2::Resource::ColorSpace::DeviceN; my $obj=PDF::API2::Resource::ColorSpace::DeviceN->new_api($self,$clrs,$samples); $self->resource('ColorSpace',$obj->name,$obj); @@ -2275,6 +2256,7 @@ sub xo_code128 { my ($self,@opts)=@_; + require PDF::API2::Resource::XObject::Form::BarCode::code128; my $obj=PDF::API2::Resource::XObject::Form::BarCode::code128->new_api($self,@opts); $self->resource('XObject',$obj->name,$obj); @@ -2286,6 +2268,7 @@ sub xo_codabar { my ($self,@opts)=@_; + require PDF::API2::Resource::XObject::Form::BarCode::codabar; my $obj=PDF::API2::Resource::XObject::Form::BarCode::codabar->new_api($self,@opts); $self->resource('XObject',$obj->name,$obj); @@ -2297,6 +2280,7 @@ sub xo_2of5int { my ($self,@opts)=@_; + require PDF::API2::Resource::XObject::Form::BarCode::int2of5; my $obj=PDF::API2::Resource::XObject::Form::BarCode::int2of5->new_api($self,@opts); $self->resource('XObject',$obj->name,$obj); @@ -2308,6 +2292,7 @@ sub xo_3of9 { my ($self,@opts)=@_; + require PDF::API2::Resource::XObject::Form::BarCode::code3of9; my $obj=PDF::API2::Resource::XObject::Form::BarCode::code3of9->new_api($self,@opts); $self->resource('XObject',$obj->name,$obj); @@ -2319,6 +2304,7 @@ sub xo_ean13 { my ($self,@opts)=@_; + require PDF::API2::Resource::XObject::Form::BarCode::ean13; my $obj=PDF::API2::Resource::XObject::Form::BarCode::ean13->new_api($self,@opts); $self->resource('XObject',$obj->name,$obj); @@ -2346,6 +2332,7 @@ sub xo_form { my ($self)=@_; + require PDF::API2::Resource::XObject::Form::Hybrid; my $obj=PDF::API2::Resource::XObject::Form::Hybrid->new_api($self); $self->resource('XObject',$obj->name,$obj); @@ -2367,6 +2354,7 @@ sub egstate { my ($self)=@_; + require PDF::API2::Resource::ExtGState; my $obj=PDF::API2::Resource::ExtGState->new_api($self,pdfkey()); $self->resource('ExtGState',$obj->name,$obj); @@ -2384,6 +2372,7 @@ sub pattern { my ($self,%opts)=@_; + require PDF::API2::Resource::Pattern; my $obj=PDF::API2::Resource::Pattern->new_api($self,undef,%opts); $self->resource('Pattern',$obj->name,$obj); @@ -2401,6 +2390,7 @@ sub shading { my ($self,%opts)=@_; + require PDF::API2::Resource::Shading; my $obj=PDF::API2::Resource::Shading->new_api($self,undef,%opts); $self->resource('Shading',$obj->name,$obj); @@ -2418,6 +2408,7 @@ sub outlines { my ($self)=@_; + require PDF::API2::Outlines; $self->{pdf}->{Root}->{Outlines}||=PDF::API2::Outlines->new($self); my $obj=$self->{pdf}->{Root}->{Outlines}; @@ -2449,6 +2440,7 @@ unless(defined $obj) { + require PDF::API2::NamedDestination; $obj=PDF::API2::NamedDestination->new_api($self); } $root->{Names}->{$cat}->{-vals}->{$name}=$obj;
Subject: pdf-api2-glyph-names.diff
diff -urN -x fonts -x 'CJKFont*' -x CMap PDF-API2-0.73/lib/PDF/API2/Util.pm ../htdocs/cgi-bin/lib/PDF/API2/Util.pm --- PDF-API2-0.73/lib/PDF/API2/Util.pm 2005-11-16 03:16:00.000000000 +0100 +++ ../htdocs/cgi-bin/lib/PDF/API2/Util.pm 2009-04-02 15:15:16.000000000 +0200 @@ -49,10 +49,8 @@ $key_var2 %u2n %n2u - %u2n_o - %n2u_o $pua - $uuu + %prio %PaperSizes ); use Math::Trig; @@ -118,10 +116,6 @@ $pua=0xE000; - %u2n_o=(); - %n2u_o=(); - - $uuu={g=>{},u=>{}}; foreach my $dir (@INC) { if(-f "$dir/PDF/API2/Resource/uniglyph.txt") { @@ -134,28 +128,18 @@ $line=~s|\s+\#.+$||go; my ($uni,$name,$prio)=split(/\s+;\s+/,$line); $uni=hex($uni); - $uuu->{u}->{$uni}||=[]; - $uuu->{g}->{$name}||=[]; - push @{$uuu->{u}->{$uni}},{uni=>$uni,name=>$name,prio=>$prio}; - push @{$uuu->{g}->{$name}},{uni=>$uni,name=>$name,prio=>$prio}; + $u2n{$uni}||=$name; + if(!defined($prio{$name}) || $prio < $prio{$name}) + { + $n2u{$name}=$uni; + $prio{$name}=$prio; + } } close($fh); + %prio=(); last; } } - foreach my $k (sort {$a<=>$b} keys %{$uuu->{u}}) - { - $u2n_o{$k}=$uuu->{u}->{$k}->[0]->{name}; - } - foreach my $k (keys %{$uuu->{g}}) - { - my($r)=sort {$a->{prio}<=>$b->{prio}} @{$uuu->{g}->{$k}}; - $n2u_o{$k}=$r->{uni}; - } - $uuu=undef; - - %u2n=%u2n_o; - %n2u=%n2u_o; %colors=(); foreach my $dir (@INC) { @@ -706,8 +690,7 @@ } sub initNameTable { - %u2n=(); %u2n=%u2n_o; - %n2u=(); %n2u=%n2u_o; + die("not implemented"); $pua=0xE000; 1; }
On Thu Apr 02 09:35:26 2009, NWELLNHOF wrote: Show quoted text
> I'm using PDF:API2 to generate PDFs on the fly on a web server. > Recently, I ran into the 32MB memory limit of a shared hosting provider. > So I had a look at the memory consumption of PDF::API2. After creating a > PDF::API2 object and loading some fonts, memory usage was about 25MB. > With the following fixes I managed to reduce that to about 15MB. > > Most of the savings can be obtained if you only "require" some of the > PDF::API2 packages when needed. See the attached patch > pdf-api2-require-packages.diff. > > I could also save about three additional MB by rewriting the code for > glyph name initialization. See the attached patch > pdf-api2-glyph-names.diff. Note that this patch breaks the function > initNameTable in PDF/API2 Util.pm. It doesn't seem to be part of the > public API, though, and it isn't used internally.
I've just started maintaining PDF::API2, and released version 2.016, which has some optimizations that lower the memory requirements by roughly 8MB according to my not-very-scientific tests. It includes a rewrite of the way the glyphs are parsed in Util.pm (different than the one you wrote -- I did the release before looking at this ticket), which lowers the startup memory requirements pretty significantly. As far as using "require" instead of "use", I'll see about making those changes, but I'm wary of doing so until the test suite covers more of the code, just in case there are unintended side effects. Instead, I'll probably do them one at a time as tests start covering each section of the code. Thanks for the patch! I'm marking this ticket as rejected, but will definitely plan to make very similar changes in future releases.