Skip to content

[BUG] Varien_Autoload dead lookups costly disk I/O #5722

Description

@kasper-agg

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When utilizing the current way plugins are designed in general, having a substantial (hard to measure actual number) amount of plugins, the Varien_Autload will iterate over a couple of directories for each class lookup.

From a recent trace, a random page caused more than 1000 non-exisitng files, just because OM has to iterate over a couple of directories to include a file.

newfstatat: Called 772 times, and 736 of them failed (returned errors).
access: Called 449 times, and 366 of them failed.

This means that during a single tiny execution loop, PHP wasted time looking for 1,100+ files on disk that do not exist.

For an idle server, disk I/O is no issue, but on slightly higher loads, it seems this can cause quite some I/O waits, even if you're runing on SSDs.

Expected Behavior

In an ideal world, we would move all modules to composer dependencies, reducing the amount of potential paths to do lookups.

However, as long as adding code to /local and /community are supported features, I believe an intermediate solution that caches dead-ends would significantly improve unnecessary disk I/O.

Expected to have the following error numbers be reduced for a "simple" php call:

 time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 32.57    0.003490           4       772       736 newfstatat
 17.37    0.001862           4       449       366 access

Steps To Reproduce

This is a bit tricky, but having a lot of custom modules in /local and/or /community, custom layouts, translations, etc. should be sufficient to measure a difference between a vanilla OM installation.

Environment

- OpenMage: 20.14.0 and 20.18.0
- php: 8.3 and 8.4

Anything else?

I think something like this could help:

app/Mage.php

public static function autoload($class)
{
    // 1. If we already know this class doesn't exist, fail instantly
    if (function_exists('apcu_fetch') && apcu_fetch('om_miss_' . $class)) {
        return false;
    }

    // [Existing OpenMage Autoload logic happens here...]
    // It loops through paths, trying to include the file.
    
    // 2. Right before the function returns false (meaning the file wasn't found):
    if (function_exists('apcu_store')) {
        // Cache this failure for 10 minutes so PHP stops looking for it on disk
        apcu_store('om_miss_' . $class, true, 600); 
    }

    return false;
}

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions