Skip to content

DBFile::getIsImage() is slow #700

@lozcalver

Description

@lozcalver

Module version(s) affected

6.1

Description

DBFile::getIsImage() is called in a number of different places when outputting images, but it is surprisingly slow and hampers performance on image-heavy pages. Given that real world servers often have restricted IOPS, I think this is worth looking at.

I’ve been benchmarking this by removing the contents of the main Page.ss to minimise any other influences, and replacing it with this:

<% loop $List('SilverStripe\Assets\Image').Limit(50) %>
	{$ScaleWidth('500')}<br />
<% end_loop %>

Loaded once to make sure all resamples have been completed.

Base benchmark:
Image

After replacing the contents of DBFile::getIsImage() with return true (not a proposed solution!):
Image

How to reproduce

<% loop $List('SilverStripe\Assets\Image').Limit(50) %>
	{$ScaleWidth('500')}<br />
<% end_loop %>

Benchmark with XHProf

Possible Solution

I’m not sure yet... I don’t think we should rely on just the file extension, as users may not have the silverstripe/mimevalidator module installed, and assets could come from other sources anyway.

Heading further down the rabbit hole, Flysystem checks whether the file exists before eventually calling this method: https://github.com/thephpleague/mime-type-detection/blob/06fd1559cc50ad3300f5ce5c16ad9a53d52ba989/src/FinfoMimeTypeDetector.php#L74-L77. Apparently that internally then looks at chunks of the file data to figure it out, which might explain the slowdown

We could store the mime type in the database, but that would need to be in a major version I think.

We could cache the result of the mime type check, but my concerns would be: (A) how big might that cache end up being? and (B) presumably we’d need to flush it whenever the file hash changed (or at the very least include the file hash in the key)?

Perhaps this isn’t solvable without significant effort, just wanted to raise it.

Additional Context

No response

Validations

  • Check that there isn't already an issue that reports the same bug
  • Double check that your reproduction steps work in a fresh installation of silverstripe/installer (with any code examples you've provided)

PRs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions