1. 程式人生 > >Java、PHP、Python、Erlang、Golang 千萬級記憶體資料插入、查詢效能對比

Java、PHP、Python、Erlang、Golang 千萬級記憶體資料插入、查詢效能對比

測試環境:
centos 6.3 64bit
php 7.2
java 1.86
python 3.4.8

Erlang/OTP 19 [erts-8.1]
golang 1.9.2

至強2.5G 4核 x 2
8 G記憶體
146g scsi x 2 raid 0+1

測試內容:
2000萬資料,每條資料一個int id,一個string name
測試建立2000萬資料的時間速度,再在這2000萬資料中查詢100條左右,計算查詢速度。
所有的語言,搜尋資料都不寫演算法、單程序(執行緒),利用語言資料型別自身的搜尋能力,避免因為演算法寫得好壞而導致的偏差

結果:

詳細結果:

測試環境:
centos 6.3 64bit
php 7.2
java 1.86
python 3.4.8

至強2.5G 4核 x 2
8 G記憶體
146g scsi x 2 raid 0+1

測試內容:
2000萬資料,每條資料一個int id,一個string name
測試建立2000萬資料的時間速度,再在這2000萬資料中查詢100條左右,計算查詢速度。
所有的語言,搜尋資料都不寫演算法,利用語言資料型別自身的搜尋能力,避免因為演算法寫得好壞而導致的偏差
=================================================================================================
php swoole.table,2000萬資料的結果
=================================================================================================
[

[email protected] swoole_test]# php7 swoole_table_test.php 
======================
Create total use 55.112974882126
Real create time 30.919550180435
======================
Real create speed 662364.10 q/s
======================
Real Row count 19250719
======================
======================
116 use 0.000099
Query Speed 1172383.77 q/s
Avg query time use 0.000001 s
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root     30836 98.8 62.9 5447960 5152052 pts/1 S+   09:30   1:00 php7 swoole_table_test.php
root     30838  0.0  0.0 106108  1156 pts/1    S+   09:31   0:00 sh -c ps aux|grep php
root     30840  0.0  0.0 103336   864 pts/1    S+   09:31   0:00 grep php


=================================================================================================
php 原生陣列,8G記憶體不夠用,下面是1000萬資料的結果
=================================================================================================
[[email protected] swoole_test]# php7 php_array_test.php 
======================
Create total use 25.156011104584
Real create time 13.448930025101
======================
Real create speed 761398.86 q/s
======================
Real Row count 9626186
======================
======================
123 use 0.000109
Query Speed 1128882.70 q/s
Avg query time use 0.000001 s

root     30863 96.9 55.7 5089968 4568848 pts/1 S+   09:38   0:25 php7 php_array_test.php
root     30865  2.0  0.0 106108  1156 pts/1    S+   09:39   0:00 sh -c ps aux|grep php
root     30867  0.0  0.0 103336   864 pts/1    S+   09:39   0:00 grep php


=================================================================================================
java hashtable做資料儲存,資料用string[]
=================================================================================================
[[email protected] swoole_test]# ./java_run.sh java_string_arr_data_test.jar
======================
Create total use 205.590419
Real create time 45.750554
======================
Real create speed 420792.19 q/s
======================
Real Row count 19251476
======================
106 use 0.000149
Query Speed 711409.40 q/s
Avg query time use 0.00000141 s
======================
[[email protected] ~]$ ps aux|grep java|test
root     31326  0.0  0.0 106108  1208 pts/1    S+   10:55   0:00 /bin/sh ./java_run.sh java_string_arr_data_test.jar
root     31327  472 78.2 10972376 6409940 pts/1 Sl+ 10:55  14:47 java -Xms512m -Xmx7012m -XX:PermSize=512m -XX:MaxPermSize=2048m -jar java_string_arr_data_test.jar


=================================================================================================
java hashtable做資料儲存,資料用class,結果浮動比較大,測試機並沒有什麼負載,列三組結果
=================================================================================================
[[email protected] swoole_test]# ./java_run.sh java_class_arr_data_test.jar
======================
Create total use 184.592579
Real create time 59.947452
======================
Real create speed 321138.54 q/s
======================
Real Row count 19251437
======================
105 use 0.000166
Query Speed 632530.12 q/s
Avg query time use 0.00000158 s
======================
[[email protected] ~]$ ps aux|grep java|grep test
root     31537  0.0  0.0 106108  1208 pts/1    S+   11:08   0:00 /bin/sh ./java_run.sh java_class_arr_data_test.jar
root     31538  455 71.0 10972372 5815956 pts/1 Sl+ 11:08  13:39 java -Xms512m -Xmx7012m -XX:PermSize=512m -XX:MaxPermSize=2048m -jar java_class_arr_data_test.jar


======================
Create total use 157.527681
Real create time 47.727919
======================
Real create speed 403343.00 q/s
======================
Real Row count 19250722
======================
104 use 0.000153
Query Speed 679738.56 q/s
Avg query time use 0.00000147 s
======================


======================
Create total use 183.524738
Real create time 65.922781
======================
Real create speed 292012.09 q/s
======================
Real Row count 19250249
======================
101 use 0.000149
Query Speed 677852.35 q/s
Avg query time use 0.00000148 s
======================


[[email protected] ~]$ ps aux|grep java|grep test
root     31684  0.0  0.0 106108  1208 pts/1    S+   11:30   0:00 /bin/sh ./java_run.sh java_class_arr_data_test.jar
root     31685  456 70.8 10972372 5800084 pts/1 Sl+ 11:30  14:00 java -Xms512m -Xmx7012m -XX:PermSize=512m -XX:MaxPermSize=2048m -jar java_class_arr_data_test.jar

=================================================================================================
python Dictionary做資料儲存,資料用tuple ,
=================================================================================================
[[email protected] swoole_test]# python python_dict_turple_test.py
======================
Create total use 687.165280
Real create time 206.128578
======================
Real create speed 99355.461494 q/s
======================
Real Row count 20480000
======================
98 use 0.001468
Query Speed 66757.49 q/s
Avg query time use 0.000015 s
======================

root     32433 99.8 55.2 4678148 4526036 pts/1 S+   13:52  11:27 python python_dict_turple_test.py
root     32470  8.0  0.0 106108  1156 pts/1    S+   14:03   0:00 sh -c ps aux|grep python|grep test

======================
python 500萬資料測試
======================
Create total use 169.645076
Real create time 51.137284
======================
Real create speed 97776.017976 q/s
======================
Real Row count 5000000
======================
111 use 0.001677
Query Speed 66189.62 q/s
Avg query time use 0.000015 s
======================

=================================================================================================
erlang erlang是一門反人類的語言,除了變數不可變而外,各種怪異的語法符號,完全是為你難以掌握而設計的。
=================================================================================================

記憶體佔得多的時候7.5G,虛擬記憶體還佔17G,但有時候又會突然下降,一會兒又漲上去了。

[[email protected] swoole_test]# ./run_erl.sh 
本次測試的是1024萬資料
資料儲存程序dict,資料Tuple,因為不知道如何取得程序字典資料量,所以每次增加之前都進行了檢查。
執行插入800萬條之後,程式“卡住”好幾分鐘,

======================
Create total use 659.250587
Real create time 25.764429
======================
Real create speed 373587.747666 q/s
======================
Real Row count 9625275
======================
90 use 0.031466 
Query Speed 2860.230090 q/s
Avg query time use 0.000349 s
======================

第二次測試同樣是卡住了,我想原因在於查詢,因為每次插入都查詢是否存在,而查詢又特別慢:
為什麼查詢慢呢,我想是因為erlang所謂變數不變造成的:因為變數不變,但資料要變,所以會大量的申請新空間來存放新的值,這會消耗大量的記憶體和cpu,
所以erlang用了巨量的虛擬記憶體,所以查詢速度,自然慢了。

======================
Create total use 1973.850796
Real create time 28.166692
======================
Real create speed 341735.834652 q/s
======================
Real Row count 9625568
======================
95 use 1.233148 
Query Speed 77.038604 q/s
Avg query time use 0.012981 s
======================
root     25053 73.9 94.0 17911268 7703228 pts/1 Sl+ 14:54   4:10 /usr/local/lib/erlang/erts-8.1/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -noshell -s erlang_list_dict_test test -s init stop

======================
Erlang&程序字典+map 500萬資料測試
======================

======================
Create total use 159.719715
Real create time 15.408685
======================
Real create speed 324492.323647 q/s
======================
Real Row count 5000000
======================
99 use 0.000510 
Query Speed 194117.647059 q/s
Avg query time use 0.000005 s
======================
root     14961 99.3 39.2 6771772 3213308 pts/0 Sl+  17:13   2:39 /usr/local/lib/erlang/erts-8.1/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -noshell -s erlang_list_dict_test test -s init stop

========================================
erlang 儲存改為ets,500萬資料測試結果。
======================
Create total use 138.476614
Real create time 36.483799
======================
Real create speed 137047.131523 q/s
======================
Real Row count 5000000
======================
99 use 0.000488 
Query Speed 202868.852459 q/s
Avg query time use 0.000005 s
======================


root     16029 99.1 33.0 5783256 2706632 pts/0 Sl+  18:11   2:19 /usr/local/lib/erlang/erts-8.1/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -noshell -s erlang_list_dict_test test -s init stop


======================
Create total use 2070.049225
Real create time 747.731820
======================
Real create speed 13694.749543 q/s
======================
Real Row count 10240000
======================
101 use 0.061205 
Query Speed 1650.191978 q/s
Avg query time use 0.000606 s
======================


root     27899 83.9 94.7 16092260 7762780 pts/1 Sl+ 18:40   5:36 /usr/local/lib/erlang/erts-8.1/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -noshell -s erlang_list_dict_test test -s init stop


root     27899 35.0 92.6 24427200 7586016 pts/1 Sl+ 18:40   6:13 /usr/local/lib/erlang/erts-8.1/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -noshell -s erlang_list_dict_test test -s init stop

==========================================
erlang ets 500萬資料結果

root     15044 99.3 33.1 5783512 2712636 pts/0 Sl+  17:21   2:18 /usr/local/lib/erlang/erts-8.1/bin/beam.smp -- -root /usr/local/lib/erlang -progname erl -- -home /root -- -noshell -s erlang_list_dict_test test -s init stop


=================================================================================================
golang map儲存所有資料,單條資料是struct,
=================================================================================================
[[email protected] swoole_test]# go build golang_data_benchmark.go
[[email protected] swoole_test]# ./golang_data_benchmark
cpu只使用50%左右
======================
Create total use 192.196030
Real create time 67.784217
======================
Real create speed 301417.627826 q/s
======================
Real Row count 20431358
======================
95 use 0.000355
Query Speed 267601.665547 q/s
Avg query time use 0.000004 s
======================


root     14226  125 42.0 3729248 3446672 pts/0 Sl+  15:25   4:05 ./golang_data_benchmark

貼2個qq群:31068495(Cocos&Unity&Java&C程式招聘),95303036(PHPer&頁遊&Mobile&U3D 2D)

測試原始碼:

Go的直接帖下面了:

package main

import ( 
    "crypto/md5"
    "encoding/hex" 
    "fmt"
	"time"
	"io"
	"crypto/rand"
	"encoding/binary"
	"bytes"
	"runtime"
)

const row_num = 20480000
const max_rd = row_num * 8
type data struct {
    id uint32
	name string
}

func Md5(str string)(string){
	//fmt.Println("Md5 str=", str)
	h := md5.New()
	h.Write([]byte(str))
	return hex.EncodeToString(h.Sum(nil))
}

func BytesToInt(b []byte) uint32 {
	bytesBuffer := bytes.NewBuffer(b)
	var tmp uint32
	binary.Read(bytesBuffer, binary.BigEndian, &tmp)
	return tmp
}

func getRd() uint32 {
	b := make([]byte, 4)

	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		return 0
	}
	return BytesToInt(b) //+uint32(mrand.Int31n(max_rd))
}

func GetTimestampInMicro()  float64{
   mil := int64(time.Now().UnixNano() / 1000)
   return float64(mil)/1000000
}

func main() {
	//runtime.GOMAXPROCS(8) 
	runtime.GOMAXPROCS(runtime.NumCPU())
	//mrand.Seed(time.Now().UnixNano())
	datas := make(map[string]data)
	search_key_sli:=make([]string , 0)
	var rd uint32
	//var value data
	
	fmt.Println("Rd_max=", max_rd, ", row_num=", row_num)
	
	var count_repeat, real_count int = 0, 0
	var real_create_ts,_start_ts, time_use float64 = 0 , 0 , 0
	start_ts := GetTimestampInMicro()

	for i := 0; i < row_num; i++ {
		var d data
		var name string
		rd = getRd() //rand.Int31n(max_rd) + 1
		//fmt.Println("Rand=" , rd)
		d.id = rd
		
		str := fmt.Sprint(rd)
		name = Md5(str)
		d.name = name
		_, ok := datas[name] 
		
		if ok{
			count_repeat ++
		}else{
			_start_ts = GetTimestampInMicro()
			datas[name] = d
			real_create_ts += GetTimestampInMicro() - _start_ts
			real_count ++
		}
		
		if rd % row_num <100{
			search_key_sli=append(search_key_sli, name)
		}
    }
	time_use = GetTimestampInMicro() - start_ts
	//real_count := len(datas)
	
	fmt.Println("Repeat=", count_repeat)
	fmt.Println("Real count by len=", len(datas))
	
	fmt.Printf("======================\n")
	fmt.Printf("Create total use %.6f\n", time_use)
	fmt.Printf("Real create time %.6f\n", real_create_ts)
	fmt.Printf("======================\n")
	fmt.Printf("Real create speed %.6f q/s\n", float64(real_count)/real_create_ts)
	fmt.Printf("======================\n")
	fmt.Printf("Real Row count %d\n", real_count)
	fmt.Printf("======================\n")
	
	var item string
	start_ts = GetTimestampInMicro()
	for _, item = range search_key_sli {
		fmt.Printf("=> name= %s\n", datas[item].name)		
    }
	time_use = GetTimestampInMicro() - start_ts
	
	fmt.Printf("%d use %.6f\n", len(search_key_sli), time_use)
	fmt.Printf("Query Speed %.6f q/s\n", float64(len(search_key_sli))/time_use)
	fmt.Printf("Avg query time use %.6f s\n", time_use/float64(len(search_key_sli)))
	fmt.Printf("======================\n")
	
	time.Sleep(time.Duration(120)*time.Second)
}