假設我們寫了一個檢查登入帳號、密碼的function,想要測試如果該function 被大量同時呼叫的話,系統會不會發生什麼狀況?這一方面也可以稍微測試一下資料庫同時能撐的連線量,因此我們可以撰寫下列的程式碼來做測試。
下列為簡易的檢查密碼的function(註:為求簡潔,忽略了帳號不存在的狀況)
%至mnesia db取帳號後檢查密碼
check(Id, Pwd)->
[Account] = mnesia:dirty_read(account, Id),
case Account#account.pwd of
Pwd->
true;
_ ->
false
end
下列為產生大量concurrent process來呼叫check(Id,Pwd)
stress_test(NProcs)->
CtrF = fun() ->
check(UserId, Pwd) %呼叫檢查帳號、密碼的function
end,
[spawn(CtrF) || _X <- lists:duplicate(NProcs, 0)].
上述的程式碼會產生數量為NProcs的Process來執行CtrF 的function,重點會是在最後一行 [spawn(CtrF) || _ <- lists:duplicate(NProcs, 0)],這是使用erlang的list comprehensions來控制程式的執行(有點類似java的for迴圈),我們先了解一下最簡單的list comprehensions,我們先看下列的code,下列的code會在console上印出1~6,
[io:format("~p~n",[X]) || X <- [1,2,3,4,5,6]]
上述執行後畫面上會出現
1
2
3
4
5
6
[ok,ok,ok,ok,ok,ok]
說明: 有1個List,裡面有6個成員分別是1,2,3,4,5,6,接著我們一次取一個成員出來並將之bind到X,每次取出成員後都會執行io:format將X的值給印出來
接下來我們來看要如何產生list裡的內容?假設我們要產生1個包含10個0的list,可以使用lists:duplicate/2,如下
lists:duplicate(10, 0)
執行結果為
[0,0,0,0,0,0,0,0,0,0]
最後我們再回頭來看 [spawn(CtrF) || _X <- lists:duplicate(NProcs, 0)].分解步驟如下
- 假設NProcs是1萬(我們要產生1萬個process來同時呼叫check(Id, Pwd))
- 首先用lists:duplicate/2來產生含1萬個0的list ex[0,0,0,0.....0],要用1來取代0也可以,反正重點在於list的長度而非list的內容
- 每次從list取出1個,並將bind到_X。為何X前要加底線?因為我們並不在意從list取出來的值是多少,所以變數X並不會用到,所以要在X前加底線,否則編譯器會出現緊告
- 最後每次都會執行spawn(CtrF),spawn在erlang裡是指會建立1個concurrent process,並執行CtrF function
短短幾行就可達到想要的處理邏輯,這就是Erlang語言的特色,不過還是得先適應function programming的思考方式才行
沒有留言:
張貼留言