Home | Back
การเปรียบเทียบประสิทธิภาพเวบระหว่าง PHP, D lang และ Go lang
Monday, 13 April 2015
ช่วงนี้อยู่ในช่วงพัฒนาระบบใหม่ ๆ จึงอยากจะหาภาษาใหม่ ๆ ที่มีประสิทธิภาพสูง ๆ รองรับงานใหญ่ ๆ ได้ จึงได้ทำการทดลองสร้างเวบที่หาค่า Fibonucci(20) แล้วแสดงผลออกมา และวัดประสิทธิภาพในการทำงานออกมา โดยผมได้ทดลองกับภาษายอดนิยม PHP กับภาษาเกิดใหม่ที่น่าสนใจคือ ภาษา D และภาษา Go โดยมีการทดลองดังนี้ครับ
1. การเตรียมเครื่องมือสำหรับการทดลอง
การทดลองผมจะทดลองบนเครื่อง PC ส่วนตัว โดยจะมี CPU Intel(R) Core(TM) i3-2100 CPU @ 3.10GHz ซึ่งมีขนาด 4 Core แบบ Logical และหน่วยความจำขนาด 8GB ทำงานบนระบบปฏิบัติการ Archlinux แบบ 64 Bits และใช้โปรแกรม wrk สำหรับวัดการตอบสนอง โดยมีผลลัพธ์เป็น Request per Seconds ซึ่งการวัดจะแบ่งวัดเป็น 3 รูปแบบ คือ 100 Concurrent, 300 Concurrent และ 1000 Concurrent โดยตัวอย่างคำสั่งที่ใช้ทดสอบดังนี้ครับ
2. การเตรียมการสำหรับภาษา PHP
สำหรับภาษา PHP ผมใช้ Web Server Front End เป็น Nginx และ ใช้ PHP-FPM ซึ่งเชื่อมต่อกันผ่าน FastCGI และเป็นภาษา PHP 5.6.7 โดยจะทำการทดลอง 2 กรณีคือ กรณีที่มี 1 Worker และ 4 Workers โดยตัวอย่าง Code ดังนี้
File : fib.php
<?php
function fib($n) {
if($n < 2) return $n;
return fib($n-1)+fib($n-2);
}
echo fib(20);
?>
3. การเตรียมการสำหรับภาษา D
สำหรับภาษา D ผมได้ใช้ Vibe.d เป็น Web Framework โดยจะทำการทดลอง 2 กรณีคือ กรณีที่มี 1 Thread และ 4 Theards โดยตัวอย่าง Code กรณี 1 Thread ดังนี้
File : one.d
import vibe.d;
import std.conv;
shared static this()
{
auto settings = new HTTPServerSettings;
settings.port = 9700;
settings.bindAddresses = ["::1", "127.0.0.1"];
listenHTTP(settings, &hello);
logInfo("Please open http://127.0.0.1:9700/ in your browser.");
}
int fib(int n)
{
if(n < 2) return n;
return fib(n-1)+fib(n-2);
}
void hello(HTTPServerRequest req, HTTPServerResponse res)
{
string d = text(fib(20));
res.writeBody(d);
}
ตัวอย่าง Code กรณี 4 Thread ดังนี้
File : multi.d
import vibe.d;
import std.conv;
shared static this()
{
auto settings = new HTTPServerSettings;
settings.port = 9700;
settings.bindAddresses = ["::1", "127.0.0.1"];
settings.options |= HTTPServerOption.distribute;
listenHTTP(settings, &hello);
logInfo("Please open http://127.0.0.1:9700/ in your browser.");
}
int fib(int n)
{
if(n < 2) return n;
return fib(n-1)+fib(n-2);
}
void hello(HTTPServerRequest req, HTTPServerResponse res)
{
string d = text(fib(20));
res.writeBody(d);
}
4. การเตรียมการสำหรับภาษา Go
สำหรับภาษา Go ผมได้ใช้ Package “net/http” ซึ่งเป็น Standard Library มาทำการทดลอง โดยจะทำการทดลอง 2 กรณีคือ กรณีที่มี 1 Thread และ 4 Theards โดยตัวอย่าง Code กรณี 1 Thread ดังนี้
File : one.go
package main
import (
"net/http"
"fmt"
)
func fib(n int) int {
if n < 2 {
return n
}
return fib(n-1)+fib(n-2)
}
func serve(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%d", fib(20))
}
func main() {
http.HandleFunc("/", serve)
http.ListenAndServe(":9700", nil)
}
ตัวอย่าง Code กรณี 4 Thread ดังนี้
File : multi.go
package main
import (
"net/http"
"fmt"
"runtime"
)
func fib(n int) int {
if n < 2 {
return n
}
return fib(n-1)+fib(n-2)
}
func serve(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%d", fib(20))
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
http.HandleFunc("/", serve)
http.ListenAndServe(":9700", nil)
}
5. ผลการทดลอง
จากการทดลอง ได้นำมาสร้างเป็นกราฟแสดงผลดังนี้ จากกราฟจะเห็นว่าประสิทธิภาพของภาษารุ่นใหม่ คือ D และ Go ค่อนข้างน่าประทับใจ แต่ดูเหมือนภาษา Go จะเหนือกว่าเล็กน้อย ในส่วนภาษา PHP น่าประหลาดใจ คือ ประสิทธิภาพที่ทดลองกรณี Concurrent ที่ 300 ขึ้นไป สามารถขึ้นไปได้สูงถึง 16000 Request per Seconds ซึ่งในขณะที่ Concurrent ที่ 100 ทำได้เพียง 300 สำหรับ 1 Worker และ 700 สำหรับ 4 Workers ซึ่งคาดว่าน่าจะเกิดจากการใช้ Caching เข้าช่วย สำหรับภาษาเกิดใหม่ ยังมีอีก 2 ภาษาที่น่าสนใจมาก ๆ คือ ภาษา Rust และ ภาษา Nim ซึ่งผมไม่ได้ทำการทดลอง เพราะเป็นภาษาที่ยังไม่เกิด version 1.00 เลย จึงทำให้ตัวภาษาและ Standard Library ยังไม่นิ่ง ซึ่งผมก็ Compile เวบทั้งสองภาษายังไม่ผ่านเลย เนื่องจากการเปลี่ยนแปลงที่ยังพัฒนาอยู่ แต่ก็น่าสนใจและติดตามอย่างยิ่ง สำหรับผมเห็นแบบนี้แล้ว คงต้องวิ่งไปหา Go ก่อนละครับ :)