Skip to content

Commit

Permalink
Only load classes and function files (#10)
Browse files Browse the repository at this point in the history
- Preloader Failing on deprecated cakephp core classes #9
- Adds new --cli option
- Only loads Classes and function files now
- Adds docker test to ensure php-fpm/cakephp loads with opcache preload enabled.
  • Loading branch information
cnizzardini authored Feb 15, 2022
1 parent 1e89139 commit e5139a7
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 22 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Merge

on:
push:
branches: [ main ]

jobs:
run:

runs-on: ubuntu-latest
strategy:
matrix:
operating-system: [ ubuntu-20.04 ]
php-versions: ['8.0']

name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }}
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, intl, xdebug

- name: PHP Version
run: php -v

- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: |
composer validate
composer install --prefer-dist --no-progress --no-suggest
- name: Test
run: vendor/bin/phpunit

- name: Report Coverage
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
composer check
echo ${{ matrix.php-versions }}
export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=clover.xml
vendor/bin/php-coveralls --coverage_clover=clover.xml -v
39 changes: 31 additions & 8 deletions .github/workflows/php.yml → .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
name: Build
name: Pull Request

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
run:
Expand All @@ -13,7 +10,7 @@ jobs:
strategy:
matrix:
operating-system: [ ubuntu-20.04 ]
php-versions: ['7.4', '8.0']
php-versions: ['7.4', '8.0', '8.1']

name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }}
steps:
Expand Down Expand Up @@ -48,7 +45,9 @@ jobs:
echo ${{ matrix.php-versions }}
export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=clover.xml
vendor/bin/php-coveralls --coverage_clover=clover.xml -v
#
# CakePHP version compatability
#
compatibility:
runs-on: ubuntu-latest
strategy:
Expand All @@ -61,7 +60,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
php-version: '7.4'
extensions: mbstring, intl

- name: PHP Version
Expand All @@ -73,4 +72,28 @@ jobs:
rm -rf composer.lock
composer require cakephp/cakephp:${{matrix.version}} --no-update
composer install --prefer-dist --no-progress
composer test
composer test
#
# Verify we can run php with opcache preload
#
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Get branch name
id: branch-name
uses: tj-actions/branch-names@v5.1
- name: Docker Build
run: docker build -t cakepreloader:test tests/ --no-cache --build-arg BRANCH=dev-${{ steps.branch-name.outputs.current_branch }}
- name: Docker Run
run: docker run -d cakepreloader:test
- name: Test Container
run: |
if docker ps | grep "cakepreloader:test"; then
echo "container is running"
else
echo "container is not running"
docker run cakepreloader:test && exit 1
fi
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Build](https://github.com/cnizzardini/cakephp-preloader/actions/workflows/php.yml/badge.svg)](https://github.com/cnizzardini/cakephp-preloader/actions/workflows/php.yml)
[![Coverage Status](https://coveralls.io/repos/github/cnizzardini/cakephp-preloader/badge.svg?branch=main)](https://coveralls.io/github/cnizzardini/cakephp-preloader?branch=main)
[![License: MIT](https://img.shields.io/badge/license-mit-blue)](LICENSE.md)
[![CakePHP](https://img.shields.io/badge/cakephp-%3E%3D%204.0-red?logo=cakephp)](https://book.cakephp.org/4/en/index.html)
[![CakePHP](https://img.shields.io/badge/cakephp-%3E%3D%204.2-red?logo=cakephp)](https://book.cakephp.org/4/en/index.html)
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.4-8892BF.svg?logo=php)](https://php.net/)

An OPCache preloader for CakePHP.
Expand All @@ -19,6 +19,10 @@ files. Goals:
composer packages.
- Provide a simplistic API for writing a custom preloader.

Any files which are not classes (i.e. Interfaces, Traits, Abstract Classes) are not added to the preload file. These
will be added automically by PHPs opcache preload if they are required by another class. Function files are loaded using
`opcache_compile_file` instead of `require_once`.

For an alternative approach, checkout [DarkGhostHunter/Preloader](https://github.com/DarkGhostHunter/Preloader).

For an OPCache UI, checkout [amnuts/opcache-gui](https://github.com/amnuts/opcache-gui).
Expand Down Expand Up @@ -59,6 +63,7 @@ Options:
--name The preload file path. (default: ROOT . DS . 'preload.php')
--packages A comma separated list of packages (e.g. vendor-name/package-name) to add to the preloader
--plugins A comma separated list of your plugins to load or `*` to load all plugins/*
--cli Should the preloader file exit when run via the php-cli? (default: true)
--quiet, -q Enable quiet output.
--verbose, -v Enable verbose output.
```
Expand All @@ -70,7 +75,7 @@ prefer handling configurations another way read the CakePHP documentation on

### Examples:

Default loads in CakePHP core files excluding TestSuite, Console, Command, and Shell namespaces. Preload file is
Default loads in CakePHP core files excluding TestSuite, Console, Command, and Shell namespaces. The preload file is
written to `ROOT . DS . 'preload.php'`:

```console
Expand Down Expand Up @@ -167,11 +172,11 @@ ab -n 10000 -c 10 http://localhost:8080/public/actors.json

I ran each 3 times:

| Type | Run 1 | Run 2 | Run 3 |
| ----------- | ----------- | ----------- | ----------- |
| No Preload | 301.30 [#/sec] (mean) | 335.12 [#/sec] (mean) | 322.41 [#/sec] (mean) |
| `CAKE` only | 447.92 [#/sec] (mean) | 448.48 [#/sec] (mean) | 446.53 [#/sec] (mean) |
| `CAKE` + `APP` | 457.62 [#/sec] (mean) | 455.40 [#/sec] (mean) | 394.89 [#/sec] (mean) |
| Type | Run 1 | Run 2 | Run 3 |
|----------------|-----------------------|-----------------------|-----------------------|
| No Preload | 301.30 [#/sec] (mean) | 335.12 [#/sec] (mean) | 322.41 [#/sec] (mean) |
| `CAKE` only | 447.92 [#/sec] (mean) | 448.48 [#/sec] (mean) | 446.53 [#/sec] (mean) |
| `CAKE` + `APP` | 457.62 [#/sec] (mean) | 455.40 [#/sec] (mean) | 394.89 [#/sec] (mean) |

## Tests / Analysis

Expand Down
6 changes: 6 additions & 0 deletions src/Command/PreloaderCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public function execute(Arguments $args, ConsoleIo $io): ?int
$path = $args->getOption('name') ?? Configure::read('PreloaderConfig.name');
$path = !empty($path) ? $path : ROOT . DS . 'preload.php';

$this->preloader->allowCli((bool)$args->getOption('cli'));
$result = $this->preloader->write($path);

if ($result) {
Expand Down Expand Up @@ -221,6 +222,11 @@ public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionPar
])
->addOption('packages', [
'help' => 'A comma separated list of packages (e.g. vendor-name/package-name) to add to the preloader',
])
->addOption('cli', [
'help' => 'Should the preloader file load when run via php-cli?',
'boolean' => true,
'default' => false,
]);

if (defined('TEST')) {
Expand Down
57 changes: 52 additions & 5 deletions src/Preloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
*/
class Preloader
{
/**
* @var bool Should the preload file continue when run via php-cli?
*/
private bool $allowCli = false;

/**
* An array of PreloadResource instances
*
Expand Down Expand Up @@ -75,12 +80,12 @@ function (SplFileInfo $file) use ($callback) {

/** @var \SplFileInfo $file */
foreach ($iterator as $file) {
if (Inflector::camelize($file->getFilename()) === $file->getFilename()) {
$result = $this->isClass($file);
if ($result === true) {
$this->preloadResources[] = new PreloadResource('require_once', $file->getPathname());
continue;
} elseif ($result === false) {
$this->preloadResources[] = new PreloadResource('opcache_compile_file', $file->getPathname());
}

$this->preloadResources[] = new PreloadResource('opcache_compile_file', $file->getPathname());
}

return $this;
Expand All @@ -104,6 +109,17 @@ public function write(string $path = ROOT . DS . 'preload.php'): bool
return (bool)file_put_contents($path, $this->contents());
}

/**
* @param bool $bool Should the preload file continue when run via php-cli?
* @return $this
*/
public function allowCli(bool $bool)
{
$this->allowCli = $bool;

return $this;
}

/**
* Returns a string to be written to the preload file
*
Expand All @@ -116,9 +132,15 @@ private function contents(): string

$title = sprintf("# Preload Generated at %s \n", FrozenTime::now());

if ($this->allowCli) {
$ignores = "['phpdbg']";
} else {
$ignores = "['cli', 'phpdbg']";
}

echo "<?php\n\n";
echo "$title \n";
echo "if (in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {\n";
echo "if (in_array(PHP_SAPI, $ignores, true)) {\n";
echo "\treturn;\n";
echo "}\n\n";
echo "require_once('" . ROOT . DS . 'vendor' . DS . 'autoload.php' . "'); \n";
Expand Down Expand Up @@ -151,4 +173,29 @@ private function contents(): string

return $content;
}

/**
* Returns false if the file name is not PSR-4, true if it as and is a class, null otherwise.
*
* @param \SplFileInfo $file Instance of SplFileInfo
* @return bool|null
*/
private function isClass(SplFileInfo $file): ?bool
{
if (Inflector::camelize($file->getFilename()) !== $file->getFilename()) {
return false;
}

$contents = file_get_contents($file->getPathname());
if (!$contents) {
return null;
}

$className = str_replace('.php', '', $file->getFilename());
if (strstr($contents, "class $className") && strstr($contents, 'namespace')) {
return true;
}

return null;
}
}
16 changes: 16 additions & 0 deletions tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM cnizzardini/php-fpm-alpine:8.0-latest

ARG BRANCH=main

COPY php.ini /usr/local/etc/php/php.ini

WORKDIR /srv/app

COPY --from=composer /usr/bin/composer /usr/bin/composer

RUN composer create-project --prefer-dist --no-interaction cakephp/app:~4.2 .
RUN composer require cnizzardini/cakephp-preloader:$BRANCH
RUN bin/cake plugin load CakePreloader
RUN bin/cake preloader

CMD ["php-fpm"]
Loading

0 comments on commit e5139a7

Please sign in to comment.