Skip to content

Commit 3f9fb8d

Browse files
author
llgoer
committed
增加项目基础文件
1 parent 17f7f31 commit 3f9fb8d

File tree

6 files changed

+258
-1
lines changed

6 files changed

+258
-1
lines changed

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.DS_Store
2+
dist
3+
php-src
4+
r2p-fib/target
5+
r2p-fib/Cargo.lock

README.md

+185-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,186 @@
11
# php-ffi-rust
2-
PHP7.4 + Rust
2+
3+
本项目目标就是采用Rust编写扩展库,提供给PHP7.4的FFI扩展,看看是否能够抢救一下PHP。
4+
5+
## 测试环境
6+
7+
macOS:10.13.6
8+
9+
PHP:7.4.0beta1
10+
11+
Rust:1.36.0
12+
13+
## 为macOS编译PHP
14+
15+
由于MacOS下没有找到合适的PHP7.4版本,所以只能自己动手编译。
16+
17+
### 下载
18+
19+
从PHP的[Github Release](https://github.com/php/php-src/releases)页面下载PHP7.4.0beta1版本。
20+
21+
### 编译PHP
22+
23+
确保系统安装`autoconf`,如果没有安装,执行`brew install autoconf`进行安装。
24+
25+
确保系统安装`bison`,`re2c`,`libffi`
26+
27+
```
28+
$ ./buildconf --force
29+
$ ./configure --prefix=/Users/llgoer/php-ffi-rust/dist --with-ffi
30+
$ make && make install
31+
```
32+
33+
这里注意,如果编译没有找到libffi,可以采用
34+
```
35+
FFI_CFLAGS=/xxx/libffi-3.2.1/include FFI_LIBS=/xxx/libffi/3.2.1/lib ./configure ...
36+
```
37+
指定
38+
39+
### 运行PHP7.4
40+
41+
进入`dist`目录,我们可以看到我们已经编译好的PHP7.4。
42+
43+
```shell
44+
$ ./php -version
45+
PHP 7.4.0beta1 (cli) (built: Aug 2 2019 22:12:05) ( NTS )
46+
Copyright (c) The PHP Group
47+
Zend Engine v3.4.0-dev, Copyright (c) Zend Technologies
48+
49+
$ ./php -m
50+
[PHP Modules]
51+
Core
52+
ctype
53+
date
54+
dom
55+
FFI
56+
fileinfo
57+
filter
58+
hash
59+
iconv
60+
json
61+
libxml
62+
pcre
63+
PDO
64+
pdo_sqlite
65+
Phar
66+
posix
67+
Reflection
68+
session
69+
SimpleXML
70+
SPL
71+
sqlite3
72+
standard
73+
tokenizer
74+
xml
75+
xmlreader
76+
xmlwriter
77+
78+
[Zend Modules]
79+
80+
```
81+
如果存在FFI扩展则表示编译正常。
82+
83+
## 安装Rust环境
84+
85+
这里就不多说了,可以去Rust官方网站看看。
86+
87+
## Rust编写一个动态连接库
88+
89+
执行
90+
91+
```shell
92+
$ cargo new r2p-fib --lib
93+
```
94+
95+
创建一个rust库,修改`Cargo.toml`,配置项目生成动态链接库
96+
97+
```toml
98+
[package]
99+
name = "r2p-fib"
100+
version = "0.1.0"
101+
authors = ["llgoer <[email protected]>"]
102+
edition = "2018"
103+
104+
[dependencies]
105+
name = "r2pfib"
106+
crate-type = ["dylib"]
107+
```
108+
109+
在lib.rs中创建一个导出的fib函数:
110+
111+
```rust
112+
#[no_mangle]
113+
pub extern fn fib(n: i32) -> i32 {
114+
return match n {
115+
1 | 2 => 1,
116+
n => fib(n - 1) + fib(n - 2)
117+
}
118+
}
119+
```
120+
121+
执行`cargo build`以及`cargo build --release`,生成对应的扩展库。
122+
123+
## 编写PHP代码
124+
125+
编写test-ffi.php
126+
```php
127+
<?php
128+
// 一个PHP的fib函数
129+
function fib($n) {
130+
if ($n < 0) {
131+
return NULL;
132+
} elseif ($n === 0) {
133+
return 0;
134+
} elseif ($n === 1 || $n === 2) {
135+
return 1;
136+
} else {
137+
return fib($n-1) + fib($n-2);
138+
}
139+
}
140+
141+
// 这里测试PHP下的Fib函数
142+
$time_start = microtime(true);
143+
for ($i=0; $i < 100000; $i++) {
144+
fib(12);
145+
}
146+
echo '[PHP]fib执行时间:' . (microtime(true) - $time_start).PHP_EOL;
147+
148+
149+
// 下面则是测试Rust的扩展,我们采用debug、release两种模式
150+
$libExtension = (PHP_OS_FAMILY == "Darwin" ? 'dylib' : 'so');
151+
152+
// debug模式
153+
$ffiDebug = FFI::cdef(
154+
"int32_t fib(int32_t n);",
155+
"r2p-fib/target/debug/libr2pfib.$libExtension");
156+
157+
$time_start = microtime(true);
158+
for ($i=0; $i < 1000000; $i++) {
159+
$ffiDebug->fib(12);
160+
}
161+
162+
echo '[Rust]Debug执行时间:' . (microtime(true) - $time_start).PHP_EOL;
163+
164+
// release模式
165+
$ffiRelease = FFI::cdef(
166+
"int32_t fib(int32_t n);",
167+
"r2p-fib/target/release/libr2pfib.$libExtension");
168+
169+
$time_start = microtime(true);
170+
for ($i=0; $i < 1000000; $i++) {
171+
$ffiRelease->fib(12);
172+
}
173+
174+
echo '[Rust]Release执行时间:' . (microtime(true) - $time_start).PHP_EOL;
175+
?>
176+
```
177+
178+
## 查看测试结果
179+
180+
执行`make test-php`查看结果,看看惊不惊喜,意不意外。
181+
182+
```
183+
[PHP]fib执行时间:3.624843120575
184+
[Rust]Debug执行时间:2.0988941192627
185+
[Rust]Release执行时间:0.56653189659119
186+
```

makefile

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
test-php:
3+
./dist/bin/php test-ffi.php

r2p-fib/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "r2p-fib"
3+
version = "0.1.0"
4+
authors = ["llgoer <[email protected]>"]
5+
edition = "2018"
6+
7+
[lib]
8+
name = "r2pfib"
9+
crate-type = ["dylib"]

r2p-fib/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#[no_mangle]
2+
pub extern fn fib(n: i32) -> i32 {
3+
return match n {
4+
1 | 2 => 1,
5+
n => fib(n - 1) + fib(n - 2)
6+
}
7+
}

test-ffi.php

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
// 一个PHP的fib函数
3+
function fib($n) {
4+
if ($n < 0) {
5+
return NULL;
6+
} elseif ($n === 0) {
7+
return 0;
8+
} elseif ($n === 1 || $n === 2) {
9+
return 1;
10+
} else {
11+
return fib($n-1) + fib($n-2);
12+
}
13+
}
14+
15+
// 这里测试PHP下的Fib函数
16+
$time_start = microtime(true);
17+
for ($i=0; $i < 100000; $i++) {
18+
fib(12);
19+
}
20+
echo '[PHP]fib执行时间:' . (microtime(true) - $time_start).PHP_EOL;
21+
22+
23+
// 下面则是测试Rust的扩展,我们采用debug、release两种模式
24+
$libExtension = (PHP_OS_FAMILY == "Darwin" ? 'dylib' : 'so');
25+
26+
// debug模式
27+
$ffiDebug = FFI::cdef(
28+
"int32_t fib(int32_t n);",
29+
"r2p-fib/target/debug/libr2pfib.$libExtension");
30+
31+
$time_start = microtime(true);
32+
for ($i=0; $i < 1000000; $i++) {
33+
$ffiDebug->fib(12);
34+
}
35+
36+
echo '[Rust]Debug执行时间:' . (microtime(true) - $time_start).PHP_EOL;
37+
38+
// release模式
39+
$ffiRelease = FFI::cdef(
40+
"int32_t fib(int32_t n);",
41+
"r2p-fib/target/release/libr2pfib.$libExtension");
42+
43+
$time_start = microtime(true);
44+
for ($i=0; $i < 1000000; $i++) {
45+
$ffiRelease->fib(12);
46+
}
47+
48+
echo '[Rust]Release执行时间:' . (microtime(true) - $time_start).PHP_EOL;
49+
?>

0 commit comments

Comments
 (0)