Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add page cache option to save memory #474

Closed
wants to merge 30 commits into from

Conversation

ssigwart
Copy link
Contributor

@ssigwart ssigwart commented Jan 25, 2022

Running example_067.php with and without the cache enabled uses about 26MB without vs 17MB with the cache.

This adds the usePageCacheFile option which allow you to move page data to a temporary file when not in use.

@ssigwart ssigwart force-pushed the pageCache branch 2 times, most recently from 89671d1 to 634d7ee Compare January 25, 2022 15:44
// Begin : 2022-01-25
// Last Update : 2022-01-25
//
// Description : Example 066 for TCPDF class

This comment was marked as resolved.

@@ -85,6 +85,7 @@
<li>Text stretching and spacing (tracking/kerning): [<a href="example_063.php" title="PDF [new window]" target="_blank">PDF</a>]</li>
<li>No-write page regions: [<a href="example_064.php" title="PDF [new window]" target="_blank">PDF</a>]</li>
<li>PDF/A-1b (ISO 19005-1:2005) document: [<a href="example_065.php" title="PDF [new window]" target="_blank">PDF</a>]</li>
<li>Using page cache to reduce memory usage: [<a href="example_066.php" title="PDF [new window]" target="_blank">PDF</a>]</li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<li>Using page cache to reduce memory usage: [<a href="example_066.php" title="PDF [new window]" target="_blank">PDF</a>]</li>
<li>Using page cache to reduce memory usage: [<a href="example_067.php" title="PDF [new window]" target="_blank">PDF</a>]</li>

tcpdf.php Outdated
Comment on lines 7903 to 7906
if ($this->pageCacheFile === false)
$this->pageCacheFile = null;
else
self::$pageCacheRefCnts[(int)$this->pageCacheFile] = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ($this->pageCacheFile === false)
$this->pageCacheFile = null;
else
self::$pageCacheRefCnts[(int)$this->pageCacheFile] = 1;
if ($this->pageCacheFile === false) {
$this->pageCacheFile = null;
} else {
self::$pageCacheRefCnts[(int)$this->pageCacheFile] = 1;
}

tcpdf.php Outdated
if ($this->pageCacheFile !== null)
{
self::$pageCacheRefCnts[(int)$this->pageCacheFile]--;
if (self::$pageCacheRefCnts[(int)$this->pageCacheFile] == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use { for your if blocks

@ssigwart
Copy link
Contributor Author

Thanks for reviewing it, @williamdes! I think I got all the changes in and updated all the ifs.

tcpdf.php Outdated
{
self::$pageCacheRefCnts[(int)$this->pageCacheFile]--;
if (self::$pageCacheRefCnts[(int)$this->pageCacheFile] == 0) {
@fclose($this->pageCacheFile); // Suppress error since this might be the end of the PHP script
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A is ressource check might remove the need of silencing an error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. I ran a test and that seems like a better way to do this. I updated it.

tcpdf.php Outdated
}
}

/** Handle cloning */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed, it feels a bit incomplete or non explained

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the comment. It's so that if you clone the object, you don't have two objects writing (and overwriting each other) to the same file.

tcpdf.php Outdated
self::$pageCacheRefCnts[(int)$this->pageCacheFile] = 1;
// Copy data
fseek($origPageCacheFile, 0, SEEK_SET);
while (($copyContent = fread($origPageCacheFile, 8192)) != false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing {

Could you add a bit more comments on what each step does?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the brace and added comments.

tcpdf.php Outdated
@@ -7866,6 +7891,60 @@ public function _destroy($destroyall=false, $preserve_objcopy=false) {
}
}

/** Page cache reference counts */
protected static $pageCacheRefCnts = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
protected static $pageCacheRefCnts = [];
protected static $pageCacheRefCnts = array();

Old php compatibility

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated this and one other place I used [].

@@ -21201,7 +21332,9 @@ public function deletePage($page) {
return false;
}
// delete current page
unset($this->pages[$page]);
if (isset($this->pages[$page])) {
unset($this->pages[$page]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit too much indentation
Same below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't understand this comment. It seems to match the other if statements.


/**
* Page cache index
* @protected

This comment was marked as resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated this.

williamdes
williamdes previously approved these changes Jan 28, 2022
Copy link
Contributor

@williamdes williamdes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is crystal clear, thank you!

Copy link
Contributor

@williamdes williamdes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

@ssigwart
Copy link
Contributor Author

ssigwart commented Feb 3, 2022

@williamdes, I assume someone else will merge this at some point, right? I don't seem to have permission.

@williamdes
Copy link
Contributor

@williamdes, I assume someone else will merge this at some point, right? I don't seem to have permission.

Yes, when Nicolas will have some time he will probably review this :)
Now we need to be patient

@ssigwart
Copy link
Contributor Author

ssigwart commented Feb 3, 2022

Sounds good. Thank you.

tcpdf.php Outdated
@@ -7866,6 +7892,60 @@ public function _destroy($destroyall=false, $preserve_objcopy=false) {
}
}

/** Page cache reference counts */
protected static $pageCacheRefCnts = array();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be non static ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intentionally have it static so that it can be shared when you clone it. The PR implements copy-on-write, so if you clone the PDF, it will share the cache until an edit is made.

I've been including this patch on production since 2019 and I haven't noticed any issues with it, so I feel like it's safer to leave this as-is, but if you want, I can remove the shared cache pages and make this non-static.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it could cause issues to users that do not expect things to be cached between pdfs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean people using the library? They would have to enable the page cache with usePageCacheFile(...) and even if they do, I have the code internally handling the caching between PDFs, so I don't think it would cause issues or be something users even know about.

If you are referring to people developing the library, that's where I think it might cause confusion, but I think I can handle that by writing more detailed comments.

If the static part is something you want to change, but still keep caching across PDFs, I could implement that with a new object for reference counting and since objects are shared by reference, it would act very similarly to the static variable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that if you can implement a version with objects that would be better than a static variable. @MauricioFauth maybe you would have input on this feature and the use of statics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added e5a3a7ce85c5c18066fcff7f87c3cf3f25fca2ad, which does it with an object instead. I'm not as confident in this change since it hasn't had years of real world testing, but it seems correct. Personally, I think this might be a little more confusing for library developers. With the static variable, I think it's more obvious that it's used to share data than this object by reference approach.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I hope someone with merge power can review this some time soon
The commit can be reverted if the static approach is preferred by the reviewer

remicollet and others added 10 commits September 6, 2023 08:51
…#620)

Tested and confirmed working in PHP 7.4 and PHP 8.2
* README: tone down the warning about tc-lib-pdf

Signed-off-by: Ruben Barkow-Kuder <github@r.z11.de>

* Update README.md

Co-authored-by: William Desportes <williamdes@wdes.fr>

---------

Signed-off-by: Ruben Barkow-Kuder <github@r.z11.de>
Co-authored-by: William Desportes <williamdes@wdes.fr>
* Fix of Deprecation warning with php 8.1 tecnickcom#614

* Update include/barcodes/qrcode.php

Co-authored-by: William Desportes <williamdes@wdes.fr>

---------

Co-authored-by: Robert Johnson Nallori <rnallori@evoketechnologies.com>
Co-authored-by: johnson361 <johnson361@users.noreply.github.com>
Co-authored-by: William Desportes <williamdes@wdes.fr>
…om#633)

* Update tcpdf_fonts.php

Fixes "use of "self" in callables is deprecated" warning is arising from tcpdf_fonts.php when using PHP >= 8.2

* Update tcpdf_fonts.php for PHP 5.3-8.2 compatibility

PHP 8.2 "use of "self" in callables is deprecated" yet some ways of fixing this breaks for PHP 5.3. This approach works, tested PHP 5.3.29 - 8.2.0

* Update tcpdf_fonts.php

Spaces added back in before arguments

* Update tcpdf_fonts.php using get_called_class()

Maneuvers compatibility of callables inside array_map() between PHP 5.3 and 8.2 - tested.

---------

Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
* Fix composite glyph output

* Pad zeros before checksum calulation

---------

Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
* fix for tecnickcom#583

* fix fix

---------

Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
* Fix non-numeric value warning

Fixes this warning on generating PDF:
Warning: A non-numeric value encountered in /tcpdf/tcpdf.php on line 5473

* Better fix for non-numeric value warning

Fixes this warning on generating PDF after calling `Text` with a non-numeric value for `$fstroke`:
Warning: A non-numeric value encountered in /tcpdf/tcpdf.php on line 5470

* Update tcpdf.php

Co-authored-by: William Desportes <williamdes@wdes.fr>

---------

Co-authored-by: William Desportes <williamdes@wdes.fr>
Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
This was already fixed in tc-lib-barcode.
mvorisek and others added 17 commits September 6, 2023 09:29
* Fix return type annotation

* BC with tools that do not support PHPStan annotations

Co-authored-by: William Desportes <williamdes@wdes.fr>

---------

Co-authored-by: William Desportes <williamdes@wdes.fr>
Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
tecnickcom#598)

* Typehints for get/setHeaderMargin are inconstent

* Add typehints for header/footer margin properties

---------

Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
* Bump actions/checkout and add PHP 8.3

* Update the composer json tests

* Remove PHP 5.3 and 5.4 from the matrix

* add permission entry

Restrict GitHub actions access

---------

Co-authored-by: Nicola Asuni <nicolaasuni@users.noreply.github.com>
Running example_068.php with and without the cache enabled uses about 26MB without vs 17MB with the cache.
@ssigwart
Copy link
Contributor Author

I rebased this to fix the merge conflicts with the examples.

@codecov-commenter
Copy link

Codecov Report

Attention: 15 lines in your changes are missing coverage. Please review.

Comparison is base (5fce932) 69.28% compared to head (f186d90) 72.96%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #474      +/-   ##
==========================================
+ Coverage   69.28%   72.96%   +3.68%     
==========================================
  Files         128      129       +1     
  Lines       26961    21974    -4987     
==========================================
- Hits        18679    16034    -2645     
+ Misses       8282     5940    -2342     
Flag Coverage Δ
php-5.3-ubuntu-latest ?
php-5.4-ubuntu-latest ?
php-5.5-ubuntu-latest ?
php-5.6-ubuntu-latest ?
php-7.0-ubuntu-latest ?
php-8.3-ubuntu-latest 72.96% <84.53%> (?)
php-nightly-ubuntu-latest 72.96% <84.53%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
examples/example_068.php 100.00% <100.00%> (ø)
include/tcpdf_page_cache_reference_counts.php 100.00% <100.00%> (ø)
tcpdf.php 71.69% <70.58%> (+3.77%) ⬆️

... and 81 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@ssigwart
Copy link
Contributor Author

I also updated this so it passes the unit tests, including on PHP 5.3.

@williamdes
Copy link
Contributor

I also updated this so it passes the unit tests, including on PHP 5.3.

Thank you !
We will have to wait on @nicolaasuni to a review

@nicolaasuni
Copy link
Member

While this is a nice feature to have, I am not keen to accept new features as the tc-lib-pdf is already working and missing only (even if very important) HTML/CSS/SVG/Javascript support.

@ssigwart
Copy link
Contributor Author

Thanks, @nicolaasuni. That makes sense. I'm looking forward to the production release of tc-lib-pdf to see how it works with some of the large CSVs I generate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.