我有一个Scotty API服务器,它构建Elasticsearch查询,从ES获取结果并呈现JSON。
与Phoenix和Gin等其他服务器相比,我使用BloodHound为服务ES响应提供更高的CPU利用率和吞吐量,但Gin和Phoenix在内存效率方面比Scotty好得多。
Scotty的统计数据
这些统计数据是在我的Mac上安装了GHC 7.10.1的情况下得出的。
处理器信息2.5GHx i5 内存信息8GB 1600 Mhz DDR3
我对GHC基于轻量级线程的并发性能印象深刻,但内存效率仍然是一个大问题。
通过分析内存使用情况,我得到了以下统计数据。
与Phoenix和Gin等其他服务器相比,我使用BloodHound为服务ES响应提供更高的CPU利用率和吞吐量,但Gin和Phoenix在内存效率方面比Scotty好得多。
Scotty的统计数据
wrk -t30 -c100 -d30s "http://localhost:3000/filters?apid=1&hfa=true"
Running 30s test @ http://localhost:3000/filters?apid=1&hfa=true
30 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 192.04ms 305.45ms 1.95s 83.06%
Req/Sec 133.42 118.21 1.37k 75.54%
68669 requests in 30.10s, 19.97MB read
Requests/sec: 2281.51
Transfer/sec: 679.28KB
这些统计数据是在我的Mac上安装了GHC 7.10.1的情况下得出的。
处理器信息2.5GHx i5 内存信息8GB 1600 Mhz DDR3
我对GHC基于轻量级线程的并发性能印象深刻,但内存效率仍然是一个大问题。
通过分析内存使用情况,我得到了以下统计数据。
39,222,354,072 bytes allocated in the heap
277,239,312 bytes copied during GC
522,218,848 bytes maximum residency (14 sample(s))
761,408 bytes maximum slop
1124 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 373 colls, 373 par 2.802s 0.978s 0.0026s 0.0150s
Gen 1 14 colls, 13 par 0.534s 0.166s 0.0119s 0.0253s
Parallel GC work balance: 42.38% (serial 0%, perfect 100%)
TASKS: 18 (1 bound, 17 peak workers (17 total), using -N4)
SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
INIT time 0.001s ( 0.008s elapsed)
MUT time 31.425s ( 36.161s elapsed)
GC time 3.337s ( 1.144s elapsed)
EXIT time 0.000s ( 0.001s elapsed)
Total time 34.765s ( 37.314s elapsed)
Alloc rate 1,248,117,604 bytes per MUT second
Productivity 90.4% of total user, 84.2% of total elapsed
gc_alloc_block_sync: 27215
whitehole_spin: 0
gen[0].sync: 8919
gen[1].sync: 30902
Phoenix 从未超过150 MB,而Gin 的内存占用要低得多。
我认为 GHC 使用标记-清除策略进行垃圾回收。我也相信使用类似于 Erlang VM 的每个线程增量 GC 策略会更好地提高内存效率。
通过解释 Don Stewart 对相关问题的回答,我认为在 GHC 中必须有一些方法可以更改 GC 策略。
我还注意到,当并发级别较低时,内存使用保持稳定且非常低,因此我认为只有在并发水平相当高时,内存使用才会急剧增加。
有什么想法/指针来解决这个问题吗?