Skip to content

zhuoyikang/elua

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

一个普通的如果执行的时间太长会阻塞调度器。

rebar compile -> 编译
erl -pa ebin +P 120000 -> 进入shell.

同步和异步nif的时间对调度器的阻塞

执行cpu数量个进程,每个进程call到lua sleep 2s.

同步nif:所有的lua代码都执行在调度器上
直接阻塞调度器,block的时候无法输出tick.
elua_block:sync().
异步nif:所以的lua代码都在单独的线程池中执行,执行完了后返回结构。
调度器安全,一切正常。
elua_block:async().

直接给出结论:

  • 本仓库已经实现了完整的异步线程池来在lua_state中执行代码。
  • 已经经过比较充分的测试,目前看无bug,代码简单易读,容易移植。
  • 每个发给lua_state的消息顺序保证不会乱,看了实现你就知道了。
  • 异步nif只是比同步nif更安全,不会阻塞erlang的调度以发生莫名其妙的事情,其他并没有什么优势。

#下面的分析已经中毒了,各位不要看。

2ms nif的并发测试

同步或者异步执行3w个lua进程。

可以在lua/block_400ms.lua中修改sleep的第1个参数作为处理ms.

-> finis 总时间 {Max,Min,Avg}

30000个同步2ms的调用, 期间会出现卡顿,CPU无法跑满2个核心以上
elua_block:r400ms_s(30000).
finis 26 {25976.904,658.49,13986.230306833386}
finis 26 {25945.968,7.806,13862.024351566612}
finis 28 {27250.5,2453.64,15311.128141300087}
finis 25 {24321.476,26.267,12693.977022566809}
30000个异步2ms的调用, 无卡顿,CPU可跑到250%.
elua_block:r400ms_a(30000).
finis 20 {19516.173,339.178,10995.266848766549}
finis 20 {19371.338,1321.542,10512.194497666595}
finis 21 {19837.564,585.391,11214.263717233302}

同步或者异步执行6w个lua进程。

60000个同步2ms的调用, 期间会出现卡顿,CPU无法跑满2个核心以上
elua_block:r400ms_s(60000).
finis 77 {75254.873,4119.663,45753.99631433323}
finis 70 {69627.56,21.015,41680.500918383135} | 1400
60000个异步2ms的调用, 无卡顿,CPU利用率稍微好点,无法跑到200%
elua_block:r400ms_a(60000).
finis 69 {67116.629,97.854,40307.205141800354}
finis 76 {74833.706,16.887,46833.761039217155} |1300
finis 67 {66317.238,16.7,40975.44325593297}  | 2000
finis 67 {65408.738,16.319,40731.685861699734}

4 worker 闲置唤醒下降到400,但是.
finis 179 {177993.277,10373.477,92834.48156833314}

16 worker
finis 167 {165790.4,17.289,81189.45815429992}

两个版本都大量的闲置唤醒。超过6W并发后,async版本也不管用,cpu无法跑到>200%

那么异步版本看上去也阻塞了调度器了,Why ?

单纯的erlang代码执行

elua_block:r400ms_pure_erlang(6000).

这行代码开启6k个erlang进程,在每个进程内跑个10ms左右的计算。在fork them all之后,cpu利用率可以达到97%,全部跑慢,不存在之前遇到的nif的跑不起cpu的情况。

cpu可以跑起来,但是明显的卡顿,用来测试单纯的无逻辑的nif消耗.
elua_block:nothing(4000).

减少并发进程数,让大量的计算在各个erlang进程中执行

elua_block:r400ms_a2(300).

用实际的计算来测试

cpu 轻松跑满,之前的sleep属于io,跑不起cpu是正常的。
elua_block:r400ms_s2(60000).
cpu 轻松跑满,之前的sleep属于io,跑不起cpu是正常的。
elua_block:r400ms_a2(60000).

所以:异步的nif和同步的nif其实只有不会阻塞调度器的区别,用起来会更安全。其他并没有什么好处。