实战1:对lager测试来分析Erlang的一些特性

目的

通过对lager进程数与打印日志数的不同组合的性能表现,分析lager在系统中对性能的影响

系统资源

一台服务器:

16CPU
64G内存

系统环境:

OS: CentOS 7.4.1708
$ cat /etc/security/limits.conf
* soft nofile 300000
* hard nofile 300000

测试方案

总体说明:

supervisor: 重启机制为simple_one_for_one
启动命令: erl +P 1002400 ...

测试代码:

F = fun(_Num,Acc)->
  supervisor:start_child(demo_lager_sup,[]),
  1+Acc
    end,
// 这儿的N是变化的进程数
lists:foldl(F,0,lists:seq(1,N)).

测试步骤:

分别测试以下几类情形下的情况
1.没有启动进程
2.1万进程
3.10万进程
4.50万进程
5.100万进程

常用命令::

erlang:process_info(pid(0,346,0), message_queue_len).

操作1:100万进程, 普通gen_server

资源占用:

系统占内存约70M
2万进程:170M
10万进程:520M
50万进程:2.26G,用时70s
100万进程:5.7G->4.6G

超出进程数时,报以下错误:

Eshell V8.3.5.4  (abort with ^G)
*** ERROR: Shell process terminated! ***

错误原因:

需要增加最大并发进程数了

操作2:100万进程,每10秒请求一次lager

变动部分:

增加:每秒每进程打印10次lager日志

关键代码:

init([]) ->
  lager:info("client process start"),
  {ok, #state{},1000}.
handle_info(_Info, State) ->
F = fun(_)->
  lager:info("=======>> handle_info _Info = ~p",[_Info]),
end,
lists:foreach(F,lists:seq(1,10)),
{noreply, State,1000}.

1万进程:

从Erlang层面:
  1.内存: 281M, 200M; 一段时间后稳定在: 390M, 285M; 
  2.CPU: 一个CPU已经占满
  3.MsgQueue: 稳定在10000(短暂时间会消耗到8000)
从系统层面:
  负载: 0.80, 0.53, 0.26
  CPU: 单cpu跑满,具体哪个CPU是变化的;短暂会出现1cpu75%,3-4cpu有5%-20%不等的占用
  内存: ->4G
其他:
  这是不能再增加哪怕一个新进程(原因应该是MsgQueue导致)
  还不准确,大约6,7s后,1个新进程创建成功.测试了下,10个新进程大约需要1分钟

10万进程:

重启后重新执行
现象:
  进程新增到13958后,新增速度极其缓慢,大约12s新增1个
Erlang层面:
  1.内存:557M, 430M(一直在很缓慢的增加)
  2.MsgQueue已经到了13000左右了
  3.Current Function固定在lager_event的{prim_file,drv_get_response,1}
系统级别:
  负载: 1万进程相同
  CPU: 1万进程基本相同
  内存: 与1万进程相同
日志写入速度:
  406秒写入了783600条日志
  每秒965条日志
说明:
  没必要再继续测试50万、100万进程了
磁盘:
[root@idc-iot-pr-server-15 hello]# iostat -x -d -k 1 10 | grep vda
Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00     5.64    0.01   15.55     0.47   243.28    31.33     0.16   10.52   11.86   10.52   2.45   3.82
vda               0.00     5.00    0.00    3.00     0.00    32.00    21.33     0.01    2.00    0.00    2.00   2.00   0.60
vda               0.00     4.00    0.00    8.00     0.00    44.00    11.00     0.01    1.75    0.00    1.75   1.75   1.40
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vda               0.00     0.00    0.00  433.00     0.00 208300.00   962.12    40.45   93.42    0.00   93.42   0.84  36.50
vda               0.00    28.00    0.00    4.00     0.00   132.00    66.00     0.06   15.50    0.00   15.50  15.50   6.20
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00
vda               0.00     0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00    0.00    0.00   0.00   0.00

结论

暂封存,有点别的事忙,此事回头再议:

When the high-water mark is exceeded, lager can be configured to flush all event notifications in the message queue. This can have unintended consequences for other handlers in the same event manager (in e.g. the error_logger'), as events they rely on may be wrongly discarded. By default, this behavior is enabled
这也许是为啥MsgQueue能维持在9999

在Matlab中,可以使用imfill函数来填充图像中的孔洞。该函数的语法如下: filled_image = imfill(binary_image, 'holes'); 其中,binary_image是二值化后的图像,'holes'表示填充孔洞。这个函数会将图像中的孔洞填充为白色(255)。 如果你不熟悉Matlab,也可以使用OpenCV来实现相同的功能。在C++中,可以使用以下代码来填充孔洞: ```cpp cv::Mat image = cv::imread("picture16.jpg", cv::IMREAD_GRAYSCALE); cv::Mat binary_image; cv::threshold(image, binary_image, 100, 255, cv::THRESH_BINARY); cv::Mat filled_image; cv::bitwise_not(binary_image, binary_image); cv::floodFill(binary_image, cv::Point(0, 0), 255); cv::bitwise_not(binary_image, filled_image); ``` 这段代码首先读取图像并进行二值化处理,然后使用漫水填充法填充孔洞,最后再将图像取反得到填充后的图像。 如果你使用Java,可以使用JavaCV库来实现相同的功能。以下是一个示例代码: ```java import org.bytedeco.opencv.opencv_core.*; import org.bytedeco.opencv.opencv_imgproc.*; public static Mat floodFill(Mat src) { Size lagerSize = new Size(src.cols() + 2, src.rows() + 2); Mat lager = new Mat(lagerSize, src.type()); Mat lager1 = lager.rowRange(1, src.rows() + 1).colRange(1, src.cols() + 1); src.copyTo(lager1); Mat src_clone = src.clone(); Imgproc.floodFill(src_clone, lager, new Point(0, 0), new Scalar(255)); Mat src_clone_inv = new Mat(); Core.bitwise_not(src_clone, src_clone_inv); Mat dst = new Mat(); Core.bitwise_or(src_clone_inv, src, dst); return dst; } ``` 这段代码使用了JavaCV库中的函数来实现漫水填充法填充孔洞。你可以将原图像传入该函数,然后得到填充后的图像。 希望这些信息对你有帮助!\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [javacv学习之实现matlab中imfill算法(孔洞填充)](https://blog.csdn.net/milerwj/article/details/120779420)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [学习杂记十六:matlab—孔洞填充实例](https://blog.csdn.net/qq_36358357/article/details/104161575)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值