freema / simdjson-polyfill
🚀 Automatic simdjson integration for PHP with multiple override strategies. Drop-in replacement for json_decode() with 3x performance boost. Symfony, Nette & Laravel support included.
Requires
- php: ^8.0
Requires (Dev)
- illuminate/support: ^8.0 || ^9.0 || ^10.0 || ^11.0
- nette/di: ^3.0
- nikic/php-parser: ^4.15 || ^5.0
- phpbench/phpbench: ^1.2
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.5 || ^10.0
- symfony/framework-bundle: ^5.4 || ^6.0 || ^7.0
- symfony/yaml: ^5.4 || ^6.0 || ^7.0
Suggests
- ext-simdjson: For 3x faster JSON parsing performance
- ext-uopz: For global json_decode() override via UopzStrategy (PHP ≤ 8.3)
- illuminate/support: For Laravel framework integration
Provides
None
Conflicts
None
Replaces
None
README
Warning
Archived, no longer maintained. No new versions will be released.
Automatic simdjson integration for PHP with multiple override strategies.
Get 3x faster JSON parsing with minimal code changes. Drop-in replacement for json_decode() with Symfony, Nette & Laravel support included.
📋 Table of Contents
- Why SimdJson?
- Installation
- Quick Start
- Strategies
- Framework Integration
- Benchmarks
- Development
- Contributing
- License
🎯 Why SimdJson?
simdjson is the world's fastest JSON parser, using SIMD instructions to parse JSON at speeds approaching 3 GB/s. This library makes it trivial to use simdjson in your PHP applications.
Performance gains:
- 🚀 3x faster JSON parsing compared to native
json_decode() - ⚡ Perfect for APIs processing large JSON payloads
- 💾 Lower CPU usage and better resource utilization
- 🔥 Zero-copy parsing when possible
📋 Requirements
- PHP 8.0 or higher (tested on PHP 8.0, 8.1, 8.2, 8.3, and 8.4)
- Composer
PHP 8.4 Note: All strategies work on PHP 8.4 except UopzStrategy, which requires PHP ≤ 8.3 due to uopz extension incompatibility.
📦 Installation
composer require freema/simdjson-polyfill
Optional (for best performance):
# Install simdjson PHP extension
pecl install simdjson
Optional (for advanced strategies):
# Install UOPZ extension for global override
pecl install uopz
🚀 Quick Start
Option 1: Safe Polyfill (Recommended)
Use JsonDecoder::decode() or fast_json_decode() instead of json_decode():
use SimdJsonPolyfill\JsonDecoder; // Using static method $data = JsonDecoder::decode($json, true); // Or using helper function $data = \SimdJsonPolyfill\fast_json_decode($json, true);
Option 2: Auto-Enable (Magic Mode)
Automatically use the best available strategy:
use SimdJsonPolyfill\SimdJsonPolyfill; // Enable once at application bootstrap SimdJsonPolyfill::enable(); // Now json_decode() uses simdjson (if using aggressive strategies) // Or use JsonDecoder::decode() for safe polyfill
Option 3: Explicit Strategy
Choose a specific strategy:
use SimdJsonPolyfill\SimdJsonPolyfill; // Use UOPZ to override json_decode() globally SimdJsonPolyfill::enable([ 'strategy' => 'uopz', 'allow_in_production' => true, // Required for production ]); // Now ALL json_decode() calls use simdjson! $data = json_decode($json, true);
🎛️ Strategies
SimdJson Polyfill offers multiple strategies with different trade-offs:
| Strategy | Risk Level | Performance | Global Override | Requires Extension |
|---|---|---|---|---|
| PolyfillStrategy | ✅ Safe | High | No | ext-simdjson |
| UopzStrategy | ⚠️ Risky | Highest | Yes | ext-uopz, ext-simdjson |
| NamespaceStrategy | ⚠️ Medium | High | Per-namespace | ext-simdjson |
| AutoPrependStrategy | ⚠️ Medium | High | Yes (manual) | ext-simdjson |
| ComposerPluginStrategy | 🔥 Very Risky | High | Yes (build-time) | ext-simdjson, nikic/php-parser |
1. PolyfillStrategy (Safe, Default)
Recommended for most use cases.
Provides JsonDecoder::decode() and fast_json_decode() functions. No magic, no risks.
use SimdJsonPolyfill\JsonDecoder; $data = JsonDecoder::decode($jsonString, true);
Pros:
- ✅ Zero risk - no global side effects
- ✅ Works everywhere
- ✅ Easy to test and debug
Cons:
- ❌ Requires code changes to use new functions
- ❌ Won't affect third-party code
2. UopzStrategy (Risky, Powerful)
⚠️ WARNING: Modifies runtime behavior globally!
Uses the UOPZ extension to override json_decode() at runtime.
SimdJsonPolyfill::enable([ 'strategy' => 'uopz', 'allow_in_production' => true, // Required! ]); // Now ALL json_decode() calls use simdjson $data = json_decode($json, true);
Pros:
- ✅ Zero code changes needed
- ✅ Affects vendor code too
- ✅ Can be toggled on/off
Cons:
- ⚠️ Requires
ext-uopz - ⚠️ May have unexpected side effects
- ⚠️ Disabled in production by default
- ❌ Not compatible with PHP 8.4+ (uopz doesn't support PHP 8.4 due to ZEND_EXIT opcode removal)
3. NamespaceStrategy (Medium Risk)
Generates namespace-specific json_decode() functions.
SimdJsonPolyfill::enable([ 'strategy' => 'namespace', 'namespaces' => ['App\\Services', 'App\\Controllers'], 'output_dir' => '/tmp/simdjson-functions', ]);
Pros:
- ✅ Scoped to specific namespaces
- ✅ More controlled than UOPZ
Cons:
- ❌ Requires namespace configuration
- ❌ Generated files need to be autoloaded
4. AutoPrependStrategy (Medium Risk)
Generates a file for PHP's auto_prepend_file directive.
SimdJsonPolyfill::enable([ 'strategy' => 'auto-prepend', 'output_file' => '/var/www/simdjson-prepend.php', ]); // Then configure php.ini: // auto_prepend_file = "/var/www/simdjson-prepend.php"
Pros:
- ✅ Global override without UOPZ
- ✅ Works for all PHP scripts
Cons:
- ⚠️ Requires php.ini configuration
- ⚠️ Affects entire PHP environment
5. ComposerPluginStrategy (Very Risky)
🔥 EXTREMELY RISKY: Modifies vendor code using AST rewriting!
Rewrites json_decode() calls in vendor/ at install time.
SimdJsonPolyfill::enable([ 'strategy' => 'composer-plugin', 'i_understand_the_risks' => true, // Required! 'create_backups' => true, 'exclude_patterns' => ['*/tests/*'], ]);
Pros:
- ✅ Build-time modification
- ✅ No runtime overhead
Cons:
- 🔥 Modifies third-party code
- 🔥 May break updates
- 🔥 Creates .bak files everywhere
- 🔥 Never auto-detected, always explicit
🔌 Framework Integration
Symfony
// config/bundles.php return [ // ... SimdJsonPolyfill\Bridge\Symfony\SimdJsonBundle::class => ['all' => true], ];
# config/packages/simdjson.yaml simdjson: enabled: true strategy: auto # or: polyfill, uopz, namespace, etc. auto_detect: true # UOPZ strategy config uopz: allow_in_production: false # Namespace strategy config namespace: namespaces: - 'App\Service' - 'App\Controller' output_dir: '%kernel.cache_dir%/simdjson'
Laravel
// config/app.php (Laravel 10 and below) 'providers' => [ // ... SimdJsonPolyfill\Bridge\Laravel\SimdJsonServiceProvider::class, ];
Laravel 11+ uses auto-discovery, no manual registration needed!
# Publish configuration (optional) php artisan vendor:publish --provider="SimdJsonPolyfill\Bridge\Laravel\SimdJsonServiceProvider" --tag="config"
// config/simdjson.php return [ 'enabled' => env('SIMDJSON_ENABLED', true), 'strategy' => env('SIMDJSON_STRATEGY', 'auto'), 'auto_detect' => env('SIMDJSON_AUTO_DETECT', true), 'uopz' => [ 'allow_in_production' => env('SIMDJSON_UOPZ_ALLOW_PRODUCTION', false), ], 'namespace' => [ 'namespaces' => [ // 'App\Services', // 'App\Http\Controllers', ], 'output_dir' => storage_path('framework/simdjson'), ], ];
.env configuration:
SIMDJSON_ENABLED=true SIMDJSON_STRATEGY=auto SIMDJSON_AUTO_DETECT=true
Nette
// config/common.neon extensions: simdjson: SimdJsonPolyfill\Bridge\Nette\DI\SimdJsonExtension simdjson: enabled: true strategy: auto autoDetect: true namespace: namespaces: - App\Services - App\Presenters
📊 Benchmarks
Results from benchmarking on PHP 8.3:
========================================
SimdJsonPolyfill Benchmark
========================================
Iterations: 10000
PHP Version: 8.3.27
simdjson extension: YES
========================================
===== File: small.json (3.3 KB) =====
json_decode 98.26 ms (0.010 ms/op) | memΔ: 4 KB | peakΔ: 0 B
simdjson_decode 35.67 ms (0.004 ms/op) | memΔ: 4 KB | peakΔ: 0 B
➡️ simdjson_decode is approximately 2.75x faster (wall-time)
simdjson (polyfill) 35.69 ms (0.004 ms/op) | memΔ: 4 KB | peakΔ: 0 B
===== File: medium.json (50.6 KB) =====
json_decode 926.56 ms (0.093 ms/op) | memΔ: 4 KB | peakΔ: 0 B
simdjson_decode 379.83 ms (0.038 ms/op) | memΔ: 4 KB | peakΔ: 0 B
➡️ simdjson_decode is approximately 2.44x faster (wall-time)
simdjson (polyfill) 378.66 ms (0.038 ms/op) | memΔ: 4 KB | peakΔ: 0 B
===== File: large.json (101.1 KB) =====
json_decode 1,833.82 ms (0.183 ms/op) | memΔ: 4 KB | peakΔ: 0 B
simdjson_decode 792.74 ms (0.079 ms/op) | memΔ: 4 KB | peakΔ: 0 B
➡️ simdjson_decode is approximately 2.31x faster (wall-time)
simdjson (polyfill) 779.16 ms (0.078 ms/op) | memΔ: 4 KB | peakΔ: 0 B
===== File: xlarge.json (500.7 KB) =====
json_decode 9,130.94 ms (0.913 ms/op) | memΔ: 4 KB | peakΔ: 1.8 MB
simdjson_decode 3,752.57 ms (0.375 ms/op) | memΔ: 4 KB | peakΔ: 376 B
➡️ simdjson_decode is approximately 2.43x faster (wall-time)
simdjson (polyfill) 3,751.59 ms (0.375 ms/op) | memΔ: 4 KB | peakΔ: 376 B
Run benchmarks yourself:
task benchmark
# or
docker-compose run --rm php php tests/Benchmark/JsonDecodeBenchmark.php
🐳 Development
This project uses Docker for development and testing, with Task as the build tool.
Prerequisites
Install Task:
# macOS brew install go-task # Linux sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin # Or see https://taskfile.dev/installation/
Setup
# Build containers task build # Install dependencies task install # Generate benchmark fixtures task fixtures
Testing
# Run all tests task test # Run tests with coverage task test-coverage # Test on all PHP versions task test-all # Run static analysis task stan
Benchmarking
# Generate fixtures task fixtures # Run benchmarks task benchmark
Available Commands
task --list # Show all available commands task shell # Open shell in PHP container task install # Install Composer dependencies task test # Run PHPUnit tests task benchmark # Run benchmarks task clean # Clean up containers and dependencies
⚠️ Warnings and Best Practices
When to Use Which Strategy
Production Applications:
- ✅ Use PolyfillStrategy - Safe, predictable, testable
- ⚠️ Consider UopzStrategy only if you thoroughly test
Development/Staging:
- ✅ Any strategy is fine for experimentation
Never Use:
- 🚫 ComposerPluginStrategy in production
- 🚫 AutoPrependStrategy without extensive testing
Safety Tips
- Always test in staging first
- Monitor for edge cases - simdjson may parse JSON slightly differently
- Have a rollback plan - disable with one config change
- Check compatibility - some JSON edge cases may behave differently
- Use version control - especially with ComposerPluginStrategy
🧪 Testing
# Unit tests vendor/bin/phpunit # With Docker make test # Test specific PHP version make test-83 # Test all versions make test-all
📄 License
MIT License. See LICENSE file for details.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
🔗 Links
- simdjson - The original C++ library
- simdjson PHP extension - PHP extension for simdjson
- Packagist
- GitHub
📮 Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with ❤️ by Tomas Grasl