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.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/freema/simdjson-polyfill
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
This package is auto-updated.
Last update: 2025-11-19 09:15:28 UTC
README
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