インフィニットループ 技術ブログ

2021年04月15日 (木)

著者 : nob

PHP が通常の2倍速!.NET で動く赤い彗星 PeachPie を使ってみた

インフラエンジニアの nobuh です。 高性能な Web サービスを簡単に構築出来ることで評判の良い Microsoft の .NET ですが、 .NET Core でオープンソース化されたことで、最近身近に感じることが多くなってきました。
そんななか、PHP のソースを事前コンパイルして .NET のランタイムで実行し、C# と PHP の相互運用を可能にするという、赤じゃなくてオレンジ色がテーマカラーのオープンソースプロジェクト PeachPie というのを見つけました。

性能では定評のある .NET Core / .NET で PHP が動くというだけでワクワクしますね! ということで早速使ってみました。

.NET 5 のインストール

今回のテストで使っているのは Ubuntu 20.04 LTS の PC です。
Microsoft の .NET 5 の Download ページUbuntu 20.04 向けパッケージマネージャーでのインストール方法 にしたがって dotnet-sdk-5.0 をインストールしました

$ dotnet --version
5.0.201

まずは動作確認で dotnet new console -o myhello で コンソールアプリケーション myhello を生成してみましょう

~$ dotnet new console -o myhello
The template "Console Application" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on myhello/myhello.csproj...
  復元対象のプロジェクトを決定しています...
  /home/n-hatano/myhello/myhello.csproj を復元しました (97 ms)。
Restore succeeded.

dotnet run で表示されるところまで確認します

~$ cd myhello/
~/myhello$ dotnet run
Hello World!

PeachPie テンプレートのインストール

次にいよいよ PeachPie をインストールします

dotnet new -i "Peachpie.Templates::*"

これだけです! dotnet new -l コマンドで現在使えるテンプレートの一覧がでます

$ dotnet new -l
Templates                                     Short Name      Language        Tags
--------------------------------------------  --------------  --------------  ----------------------
Console Application                           console         [C#],F#,PHP,VB  Common/Console
Class library                                 classlib        [C#],F#,PHP,VB  Common/Library
  *
  *
  *
ASP.NET Core Empty                            web             [C#],F#,PHP     Web/Empty
  *
  *
  *

php で作成可能なのは Console ApplicationClass library、シンプルな Web アプリの ASP.NET Core Empty の3つになります

PHP で Hello World

まずはコンソールアプリケーションで Hello World を表示する HelloPHP を作成してみましょう

$ dotnet new console -lang PHP -o HelloPHP
The template "Console Application" was created successfully.

これだけです。ディレクトリに移って dotnet run してみます

~$ cd HelloPHP/
~/HelloPHP$ dotnet run
HelloPHP says: "Hello World!"

無事実行されました! 生成された PHP のソース Program.php を見てみましょう

<?php
function main()
{
    echo "HelloPHP says: \"Hello World!\"";
}
main();

echo 文1行、ではなくて main 関数を定義するかたちになっています。main 関数は別に必須ではなく echo 1行だけに変更しても問題なく動きます。

Web アプリケーションの作成

MVC ではない素の ASP.NET Core の Web アプリケーションを作成します。PeachPie のドキュメントには

dotnet new web -lang PHP

で作成出来るというように記述されていますが、手元の環境では webapp2 の ASP.NET MVC のテンプレートを探しにいってしまい、それは PHP は対応していないため、上手く作成出来ませんでした。
ここは web ではなく長い名前の “ASP.NET Core Empty” を指定することで作成することが出来ます。

~$ dotnet new "ASP.NET Core Empty" -lang PHP -o HelloWeb
The template "ASP.NET Core Empty" was created successfully.

作成されたディレクトリとファイルの構成は以下のようになっていて

├── HelloWeb.sln
├── README.md
├── Server
│   ├── Program.cs
│   └── Server.csproj
└── Website
    ├── Website.msbuildproj
    └── index.php

Website ディレクトリに index.php があり、

<?php
echo "HelloWeb says \"Hello World!\"";

Server ディレクトリにはコンパイルされた PHP のコードを呼び出す ASP.NET Core の Kestrel を使った Web アプリケーションが配置されています
動かすにはこの Server の方で dotnet run します

~/HelloWeb/Server$ dotnet run
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using '/home/n-hatano/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
Hosting environment: Production
Content root path: /home/n-hatano/HelloWeb/Server
Now listening on: http://[::]:5004
Application started. Press Ctrl+C to shut down.

ポート 5004 でリッスンされていますのでブラウザでアクセスしてみます

無事表示されました!

Apache bench で apache(mod_php) と ASP.NET(PeachPie) の速度を比較してみる

最初に Apache での速度を計測します。 Apache は 2.4 PHP のバージョンは 7.4 です

$ apache2 -v
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2020-08-12T19:46:17
$ php -v
PHP 7.4.3 (cli) (built: Oct  6 2020 15:47:56) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.3, Copyright (c), by Zend Technologies

PeachPie が生成した index.php を持つ Website ディレクトリをそのまま apache のドキュメントルートにしました。他はデフォルトです。
使っているマシンのスペックは以下になります

  • Ubuntu 20.04
  • Core i3-7100U
  • メモリ 16GB

apache bench を同時実行を増やしながら行い、実行数 (-n) 100,000 同時実行 (-c) 1000 で残念ながらコネクション数関係と思われるエラーが 10 件発生してしまいました。
このときのスループットも 2700 リクエスト/秒 くらいがピークのようです

$ ab -n 100000 -c 1000 http://127.0.0.1/
*
*
*
Concurrency Level:      1000
Time taken for tests:   36.845 seconds
Complete requests:      100000
Failed requests:        10
   (Connect: 0, Receive: 0, Length: 10, Exceptions: 0)
Total transferred:      19198848 bytes
HTML transferred:       2499850 bytes
Requests per second:    2714.05 [#/sec] (mean)
Time per request:       368.453 [ms] (mean)
Time per request:       0.368 [ms] (mean, across all concurrent requests)
Transfer rate:          508.85 [Kbytes/sec] received

次に dotnet run で .NET の Kestrel サーバーでの同一条件の性能を測ってみます

Concurrency Level:      1000
Time taken for tests:   17.017 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      23100000 bytes
HTML transferred:       2800000 bytes
Requests per second:    5876.44 [#/sec] (mean)
Time per request:       170.171 [ms] (mean)
Time per request:       0.170 [ms] (mean, across all concurrent requests)
Transfer rate:          1325.64 [Kbytes/sec] received

エラーなく終了し、スループットも 5800 リクエスト/秒

2倍の性能を出すことが出来ました! これが新型 .NET の性能なのか・・・

今回は MySQL へのアクセスを含んでいませんし、事前コンパイルされるらしい Composer のオートロード周りの処理も確認したわけではなく、あくまで1行 php の性能の比較に過ぎませんので、過信は禁物です。
とはいえ、PHP と MySQL のチューニングにおいてはソケットやセッションといったコネクション周りの問題がボトルネックとなり最大の障害となりますが、同時接続性能の高い .NET はパフォーマンスチューニングの点でも魅力的で、PHP と C# の相互運用が可能になる PeachPie の今後の動向には注目して行きたいと思います
インフィニットループでは PHP や MySQL、インフラの面白い技術を一緒に追求してくれる方々を歓迎しています!
ぜひご応募ください!

ブログ記事検索

このブログについて

このブログは、札幌市・仙台市の「株式会社インフィニットループ」が運営する技術ブログです。 お仕事で使えるITネタを社員たちが発信します!