Categories

# Supercharge PHP using FFI

As we all know that PHP is an open-source general-purpose scripting language. It is a type of simple and easy-to-write language which is good, but sometimes it brings some performance penalty. In this article, we are trying to remove those performance penalties using FFI (Foreign Function Interface). So, let’s get started.

As we all know that PHP is an open-source general-purpose scripting language. It is a type of simple and easy-to-write language which is good, but sometimes it brings some performance penalty.

In this article, we are trying to remove those performance penalties using FFI (Foreign Function Interface). So, let’s get started.

## Today’s challenge is to make a Fibonacci number generator.

### Let’s try to solve that using PHP

Suppose we are trying to calculate the Fibonacci number in PHP, and here is the simple Fibonacci number generator function below.

``````function fib(int \$n) {
if (\$n === 1 || \$n === 2) {
return 1;
}

return fib(\$n - 1) + fib(\$n - 2);
}``````

Above, we have created a function named `fib` that takes one number argument and returns its Fibonacci value.

Let’s create a PHP file and execute that function in the terminal using PHP binary prefix with the `time` command, So we can get the elapsed time of the executed script.

``print_r(fib(20));``

After running our script we get the following output in our terminal.

Above, `6765` is the Fibonacci value of `20`, And the total elapsed time is `0.033s`.

That was quick! let’s give the higher number to `fib` function. This time we give 40 to `fib` function.

``print_r(fib(40));``

After running the script we get the following output in our terminal.

As you know from the previous example, this time we get `102334155` the value of `fib(40)`, and the total elapsed time is `7.100s`.

### Let’s try now using FFI in PHP

First, I should tell you that FFI is not magic that magically boosts your code. FFI is a PHP extension and this is the following definition from the PHP website.

So we need to learn the C language, right? The answer is No. You could write using C but alternatively, you could use another language and compile into C style shared library. In our example, we will use Rust programming language. So let’s code.

First, we need to create a library project. In rust, we will use Cargo to handle it.

Now write the rust implementation of the Fibonacci number generator function.

``````fn fib(n: i64) -> i64 {
return match n {
1 | 2 => 1,
n => fib(n - 1) + fib(n - 2)
}
}``````

OK, now tell the compiler `fib` function should expose for FFI.

``````pub extern "C" fn fib(n: i64) -> i64 {
return match n {
1 | 2 => 1
n => fib(n - 1) + fib(n - 2)
}
}``````

Before starting to compile our code, we should tell one more thing to Rust compiler, stop mangling the function name by using `#[no_mangle]` attribute.

``````#[no_mangle]
pub extern "C" fn fib(n: i64) -> i64 {
return match n {
1 | 2 => 1
n => fib(n - 1) + fib(n - 2)
}
}``````

And now we have to tell the rust compiler, the output binary should be a dynamic system library. So, it will produce `*.dll` file for Windows, `*.dylib` file for macOS and `*.so` file for Linux.

``````[lib]
crate-type=["cdylib"]``````

We need to add the two lines above to `Cargo.toml` file.

Now we need to compile our rust code. Just run the build command of cargo.

This will produce the binary file to the `ffi>target>debug` directory. I am on macOS So, In my case, my code was compiled into the `*.dylib` file.

Now we will use the file with our PHP code using FFI.

``````\$ffi = FFI::cdef('long long fib(long long n);', __DIR__ . '/ffi/target/debug/libffi.dylib');

print_r(\$ffi->fib(20));``````

In this example, we use the `cdef` method of PHP `FFI` class to load our library file. In C you have to define the function signature before the `main` function, If your function is declared after the `main` function. In that case, you have to declare the function definition on the first parameter of the `cdef` method, and the second parameter will take the path of the library file. And it will give us the exposed function as a method. In that case, the method name is the `fib`.

`long long` is a type that is used in C to represent 64-bit numbers.

So, run the first example, where `n=20`

And surprisingly it took `0.046s` to complete. Whereas PHP implementation was took only `0.36s`.

Let’s try on our second example, where `n=40`

Aaha! It took just `0.453s` to complete. Whereas PHP implementation is taken `7.1s` to complete.

At this moment you may be thinking this is the end of the comparison. But we haven’t unveiled our main power, the RELEASE BUILD.

### PHP + FFI (RUST Release Build)

In this step, we are going to tweak some build configurations to tell the Rust compiler, This build is for production use so try to optimize our binary as much as possible. For this reason, we need to add the following configuration lines to `Cargo.toml` file.

``````[profile.release]
opt-level = 'z'
lto = true
codegen-units = 1``````

Now build the library using `--release` flag

This will create a new directory named `release` and compile the library into that directory. So we need to modify the library path into the FFI loading PHP code. And then try to execute it to `n=40`.

This time it took only `0.222s`. That is half of the previous elapsed time of FFI + Rust Unoptimized.

Now let’s see the overall results in a chart

OK, I know you want to see the full benchmark details which is not possible by the above image. Here is the data

### Conclusion

As you see from the examples, Simple computation is fine for PHP. Do not overengineer the simple tasks with complex steps, Like using FFI or building a native PHP extension, etc. Use them wisely and thanks for reading the entire article. ## By Mehedi Hasan

Hi!
I am Mehedi Hasan, work as a Software Engineer at weDevs. I love to experiment with the latest tech and make something that solves some problems of others and mine. Also in my free time, I like to read religious books on Islam.

## 2 replies on “Supercharge PHP using FFI” Md Nobir Hasansays:

Vai, Php file ki robust use kora jabe??Mane javascript and php jemon aksathe likha jai??

আপনি robust বলতে rust বুঝিয়েছেন? যদি তাই হয় তাহলে, উত্তরঃ PHP ফাইল এ rust লেখা যাবে না । আপনি Rust কোড কে কম্পাইল করে ব্যবহার করতে পারবেন যেটি এখানে দেখানো হয়েছে।