Skip to content

Load mime-types lazily: require 'playwright' allocates 63% fewer objects - #399

Open
czj wants to merge 1 commit into
YusukeIwaki:mainfrom
czj:lazy-mime-types
Open

czj wants to merge 1 commit into
YusukeIwaki:mainfrom
czj:lazy-mime-types

Conversation

@czj

@czj czj commented Oct 24, 2026

Copy link
Copy Markdown

Hi Yusuke, and thank you for keeping this client so close to upstream Playwright!

Route and ScreenshotUtils require mime/types at the top of their files, and since channel_owner.rb loads every channel owner, each require 'playwright' loads the whole MIME database. Yet it is only consulted in two places: Route#fulfill(path:), to guess the content type, and screenshot(path:) without an explicit type:. Most test suites never reach either, but they pay the load cost on every boot, and Rails apps that eager-load their test dependencies pay it in every process.

This PR moves the require into those two methods, as playwright.rb already does for playwright/web_socket_client. require is thread-safe and becomes a cheap lookup after the first call. I added a unit spec for ScreenshotUtils.determine_type (which had none) and one that checks, in a subprocess, that require 'playwright' no longer loads mime/types. That spec fails on main.

Measured with ruby -I lib -e "require 'playwright'" (no Bundler), Ruby 4.0.8 arm64, mime-types 3.7.0, median of 5 runs:

require 'playwright' main this branch
Wall time 173 ms 124 ms (−28%)
Allocated objects 214,866 80,194 (−63%)
Live objects after GC 69,539 45,104 (−35%)
ObjectSpace.memsize_of_all 5.1 MB 2.5 MB
RSS 30.5 MB 26.7 MB

The unit suite passes (36 examples, 2 pending as before), and so do request_fulfill_spec, route_spec and screenshot_spec against playwright-core 1.64.0 on Chromium (41 examples). I also checked by hand that route.fulfill(path: 'empty.html') still answers with text/html.

One thing to be aware of: code that used MIME::Types without requiring it, relying on Playwright to load it, would now need its own require 'mime/types'.


🤖 Generated with Claude Code, but prompted, read, and verified by @czj, a caring human :)

Route and ScreenshotUtils required 'mime/types' at load time, so every
`require 'playwright'` paid for the whole MIME database even though it
is only consulted by `Route#fulfill(path:)` and by screenshots given a
`path:` without a `type:`.

Requiring it inside those two methods, as playwright.rb already does
for the WebSocket transport, cuts `require 'playwright'` from about
215k to 80k allocated objects and about 3.8 MB of RSS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 24, 2026

Copy link
Copy Markdown

@czj is attempting to deploy a commit to the Yusuke Iwaki's projects Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant