Project

General

Profile

Actions

Feature #44396

closed

Reduce memory usage by not loading rbpdf until a PDF is generated

Added by Go MAEDA 22 days ago. Updated 14 days ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Performance
Target version:
Resolution:
Fixed

Description

Redmine loads the rbpdf gem at every boot, even though it is only needed for PDF export. This patch defers loading it until a PDF is actually generated. In my measurements, this reduced the median RSS by about 12 MB, from 217.8 MB to 205.9 MB. Processes that do not export PDFs can therefore avoid loading rbpdf and its dependencies for their whole lifetime.

The first patch fixes the existing RuboCop offenses in lib/redmine/export/pdf.rb so that moving ITCPDF in the second patch does not require updating .rubocop_todo.yml.

The second patch makes the following changes:

1. Adds require: false to gem 'rbpdf' so that Bundler does not load rbpdf at boot.
2. Moves the ITCPDF class to a new file, lib/redmine/export/pdf/itcpdf.rb, where rbpdf is explicitly required. RDMPdfEncoding stays in lib/redmine/export/pdf.rb because it does not depend on rbpdf.
3. Excludes the new file from eager loading with loader.do_not_eager_load. The file remains autoloadable, so it and rbpdf are loaded when Redmine::Export::PDF::ITCPDF is first referenced.

I measured the effect by booting a production environment and reading the RSS of the process:

for i in 1 2 3 4 5; do bin/rails r -e production 'GC.start; puts "RSS=#{`ps -o rss= -p #{$$}`.to_i}KB rbpdf=#{$LOADED_FEATURES.grep(%r{/rbpdf-}).any?}"'; done

macOS 15 (arm64), Ruby 3.4.8, SQLite3, no plugins, assets already precompiled, 5 runs each:

RSS median RSS range rbpdf loaded
trunk 217.8 MB 212.5–218.7 MB yes
patched 205.9 MB 205.5–208.5 MB no

With the patch, rbpdf, rbpdf-font, and htmlentities are no longer loaded at boot.

With a preforking server such as Puma in cluster mode, loading rbpdf in the master process allows its memory to be shared with workers through copy-on-write. An installation that exports PDFs often can keep the old behavior by adding require 'rbpdf' to config/additional_environment.rb.


Files

Actions #1

Updated by Go MAEDA 19 days ago

  • Target version changed from Candidate for next major release to 7.1.0

Setting the target version to 7.1.0.

Actions #2

Updated by Go MAEDA 14 days ago

  • Status changed from New to Closed
  • Assignee set to Go MAEDA
  • Resolution set to Fixed

Committed the patch in r25046 and r25047.

Actions

Also available in: Atom PDF