Child pages
  • [caching] Store class/unit map in disk cache [5.3.0-B1]
Skip to end of metadata
Go to start of metadata

This article will be about:

  • class map - allows to determine PHP file, that contains any class/interface/trait declaration
  • unit map - allows to determine PHP file, that has given unit config declaration

Currently both maps are stored either in database or memcache (only when memcache is installed). It works, but requires first to make a connection to database/memcache to get the current map version. Unfortunately this can end up in Fatal Error (e.g. [deployment] Trait usage results in fatal error during deploy [5.2.1]) because we use we're able to determine it's location.

Solution

  1. each module will have following files:
    1. {module_path}/install/cache/class_map.php (e.g. /modules/in-link/install/cache/class_map.php, /core/install/cache/class_map.php)
    2. {module_path}/install/cache/unit_map.php
  2. each file would start with following line to ensure that it's never checked by any static analysis tools (e.g. PHP_CodeSniffer, Phabricator): // This file is @generated automatically
  3. introduce "Generate class/unit maps" button in "System Tools", which only action would be to rebuild these map files
  4. don't ever reset these map files by any automatic action, e.g. unit config cache rebuild or deploy
  5. always include map files from all modules once we know what modules are installed
  6. the class map files would go directly to kFactory and will power auto-loader
  7. the unit map files would go directly to unit config reader and power the "getUnitConfigOption" and similar stuff

The proposed change will eliminate the situation, where a new file was discovered in the middle of application initialization and it can be used only on next page load, because it's not in cache. E.g. no custom rewrite listener is able to handle page load that triggered cache rebuild.

Related Discussions

Related Tasks

INP-1422 - Getting issue details... STATUS

4 Comments

  1. The catch in above changes is fact, that:

    • modules are allowed to replace classes, defined in other modules
    • unit configs can have priority specified and will be processed after other unit configs were processed
  2. In fact this can be approached from different angle:

    • use https://github.com/nikic/PHP-Parser to statically analyze codebase and figure out file, where each class/interface/trait is declared (autoloader already takes care of dependencies)
    • keep single class map per module (the /core/ folder and each sub-folder in /modules/ that have install.php file)
    • the class factory (kFactory class) automatically includes these files without need to figure out what module is enabled (side effect: ability to use classes from disabled/not installed modules)
  3. I've been able to create a prototype and here are the benchmarks:

    Processing ".../core" folder:

    • Scan duration: 0.0136s
    • Parse duration: 27.6406s

    Processing ".../modules/in-link" folder:

    • Scan duration: 0.0015s
    • Parse duration: 1.1987s

    Processing ".../modules/in-news" folder:

    • Scan duration: 0.0008s
    • Parse duration: 0.4297s

    Processing ".../modules/in-bulletin" folder:

    • Scan duration: 0.0020s
    • Parse duration: 1.0361s

    Processing ".../modules/in-commerce" folder:

    • Scan duration: 0.0069s
    • Parse duration: 8.9530s

    Processing ".../modules/in-auction" folder:

    • Scan duration: 0.0023s
    • Parse duration: 2.7104s

    Processing ".../modules/custom" folder:

    • Scan duration: 0.0020s
    • Parse duration: 0.2988s

    Explanation:

    • Scan duration - how long it took to locate all PHP files in a given folder
    • Parse duration - how long it took to parse each found PHP file in given folder to detect what class/interface/trait is declared in it

    27 seconds for ".../core" folder might sound like a lot, but keep in mind that all of above:

    • will only happen on developer machine (no such cache will be never rebuild automatically, e.g. during deployment/page visit on staging/production servers)
    • will only happen for files, that developer adds/changes (all unchanged files will be read from cache)
    • these cache is files are committed to version control system (VCS) so no rebuilding on each page load either

    Benefits:

    • no need to specify file where class/interface/trait is declared ever
    • no need to worry about non using PHP 5.3 namespaces or PSR-0 compliant auto-loader
  4. Output of building script now looks better: