Erlang open_port极度影响性能的因素

问题描述

Erlang的port相当于系统的IO,打开了Erlang世界通往外界的通道,可以很方便的执行外部程序。 但是open_port的性能对整个系统来讲非常的重要,我就带领大家看看open_port影响性能的因素。首先**open_port的文档: {spawn, Command} Starts an external program. Command is the name of the external program which will be run. Command runs outside the Erlang work space unless an Erlang driver with the name Command is found. If found, that driver will be started. A driver runs in the Erlang workspace, which means that it is linked with the Erlang runtime **. When starting external programs on Solaris, the ** call vfork is used in preference to fork for performance reasons, although it has a history of being less robust. If there are problems with using vfork, setting the environment variable ERL_NO_VFORK to any value will cause fork to be used instead. For external programs, the PATH is searched (or an equivalent method is used to find programs, depending on operating **). This is done by invoking the shell och certain platforms. The first space separated token of the command will be considered as the name of the executable (or driver). This (among other things) makes this option unsuitable for running programs having spaces in file or directory names. Use {spawn_executable, Command} instead if spaces in executable file names is desired.open_port一个外部程序的时候流程大概是这样的:beam.smp先vfork, 子进程调用child_setup程序,做进一步的清理**作。 清理完成后才真正exec我们的外部程序。再来**open_port实现的代码:// sys.c:L135202static ErlDrvData spawn_start(ErlDrvPort port_num, char* name, SysDriverOpts* opts)03{04...05#if !DISABLE_VFORK06 int no_vfork;07 size_t no_vfork_sz = sizeof(no_vfork);08 09 no_vfork = (erts_sys_getenv("ERL_NO_VFORK",10 (char *) &no_vfork,11 &no_vfork_sz) >= 0);12#endif13...14else { /* Use vfork() */15 char **cs_argv= erts_alloc(ERTS_ALC_T_TMP,(CS_ARGV_NO_OF_ARGS + 1)*16 sizeof(char *));17 char fd_close_range; /* 44 bytes are enough to */18 char dup2_op; /* hold any "%d:%d" string */19 /* on a 64-bit machine. */20 21 /* Setup argv[] for the child setup program (implemented in 22 erl_child_setup.c) */23 i = 0;24 if (opts->use_stdio) {25 if (opts->read_write & DO_READ){26 /* stdout for process */27 sprintf(&dup2_op, "%d:%d", ifd, 1);28 if(opts->redir_stderr)29 /* stderr for process */30 sprintf(&dup2_op, "%d:%d", ifd, 2);31 }32 if (opts->read_write & DO_WRITE)33 /* stdin for process */34 sprintf(&dup2_op, "%d:%d", ofd, 0);35 } else { /* ** will fail if ofd == 4 (unlikely..) */36 if (opts->read_write & DO_READ)37 sprintf(&dup2_op, "%d:%d", ifd, 4);38 if (opts->read_write & DO_WRITE)39 sprintf(&dup2_op, "%d:%d", ofd, 3);40 }41 for (; i use_stdio ? 3 : 5, max_files-1);44 45 cs_argv = child_setup_prog;46 cs_argv = opts->wd ? opts->wd : ".";47 cs_argv = erts_sched_bind_atvfork_child(unbind);48 cs_argv = fd_close_range;49 for (i = 0; i spawn_type == ERTS_SPAWN_EXECUTABLE) {52 int num = 0;53 int j = 0;54 if (opts->argv != NULL) {55 for(; opts->argv != NULL; ++num)56 ;57 }58 cs_argv = erts_realloc(ERTS_ALC_T_TMP,cs_argv, (CS_ARGV_NO_OF_ARGS + 1 + num + 1) * sizeof(char *));59 cs_argv = "-";60 cs_argv = cmd_line;61 if (opts->argv != NULL) {62 for (;opts->argv != NULL; ++j) {63 if (opts->argv == erts_default_arg0) {64 cs_argv = cmd_line;65 } else {66 cs_argv = opts->argv;67 }68 }69 }70 cs_argv = NULL;71 } else {72 cs_argv = cmd_line; /* Command */73 cs_argv = NULL;74 }75 DEBUGF(("Using vforkn"));76 pid = vfork();77 78 if (pid == 0) {79 /* The child! */80 81 /* Observe! 82 * OTP-4389: The child setup program (implemented in 83 * erl_child_setup.c) will perform the necessary setup of the 84 * child before it execs to the user program. This because 85 * vfork() only allow an *immediate* execve() or _exit() in the 86 * child. 87 */88 execve(child_setup_prog, cs_argv, new_environ);89 _exit(1);90 }91 erts_free(ERTS_ALC_T_TMP,cs_argv);92...93}在支持vfork的系统下,比如说linux,除非禁止,默认会采用vfork来执行child_setup来调用外部程序。**vfork的文档: vfork() differs from fork() in that the parent is suspended until the child makes a call to execve(2) or _exit(2). The child shares all memory with its parent, including the stack, until execve() is issued by the child. The child must not return from the current function or call exit(), but may call _exit().vfork的时候beam.smp整个进程会被阻塞,所以这里是个很重要的性能影响点。我们再**erl_child_setup.c的代码:// erl_child_setup.c:11102// 1. 取消绑定03if (strcmp("false", argv) != 0)04 if (erts_unbind_from_cpu_str(argv) != 0)05 return 1;06// 2. 复制句柄07 for (i = 0; i 6 _ = ,7 Port = open_port({spawn, "/bin/cat"}, ),8 port_close(Port),9 ok.我们再准备个stap脚本,用来分析这些行为和性能数字:$ cat demo.stp02global t0, t1, t203 04probe process("beam.smp").function("spawn_start") {05 printf("spawn %sn", user_string($name))06 t0 = gettimeofday_us()07}08 09probe process("beam.smp").statement("*@sys.c:1607") {10 t1 = gettimeofday_ns()11}12 13probe process("beam.smp").statement("*@sys.c:1627") {14 printf("vfork take %d nsn", gettimeofday_ns() - t1);15}16 17probe process("child_setup").function("main") {18 t2 = gettimeofday_us()19}20 21probe process("child_setup").statement("*@erl_child_setup.c:111") {22 t3 = gettimeofday_us()23 printf("spawn take %d us, child_setup take %d usn", t3 - t0, t3 - t2)24}25 26probe syscall.execve {27 printf("%s, arg %sn", name, argstr)28}29 30probe syscall.fork {31 printf("%s, arg %sn", name, argstr)32}33 34probe begin {35 println(")");我们在一个终端下运行stap脚本观察行为:$ erlc demo.erl02$ PATH=otp/bin/x86_64-unknown-linux-gnu/:$PATH sudo stap demo.stp03)04fork, arg05execve, arg otp/bin/erl06fork, arg07fork, arg08fork, arg09execve, arg /bin/sed "s/.*\///"10execve, arg /home/chuba/otp/bin/x86_64-unknown-linux-gnu/erlexec11execve, arg /home/chuba/otp/bin/x86_64-unknown-linux-gnu/beam.smp "--" "-root" "/home/chuba/otp" "-progname" "erl" "--" "-home" "/home/chuba" "--"12clone, arg .13..14clone, arg CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID15spawn inet_gethost 416fork, arg17execve, arg /home/chuba/otp/bin/x86_64-unknown-linux-gnu/child_setup "FFFF" "." "exec inet_gethost 4 " "3:327679" "8:1" "9:0" "-"18vfork take 8487 ns19spawn take 173707 us, child_setup take 94535 us20execve, arg /bin/sh "-c" "exec inet_gethost 4 "21execve, arg /home/chuba/otp/bin/x86_64-unknown-linux-gnu/inet_gethost "4"22fork, arg23clone, arg CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID24clone, arg CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID25spawn /bin/cat26fork, arg27execve, arg /home/chuba/otp/bin/x86_64-unknown-linux-gnu/child_setup "FFFF" "." "exec /bin/cat" "3:327679" "2312:1" "2313:0" "-"28vfork take 5298 ns29spawn take 180974 us, child_setup take 101646 us30execve, arg /bin/sh "-c" "exec /bin/cat"31execve, arg /bin/cat32spawn /bin/cat33fork, arg34execve, arg /home/chuba/otp/bin/x86_64-unknown-linux-gnu/child_setup "FFFF" "." "exec /bin/cat" "3:327679" "3080:1" "3081:0" "-"35vfork take 8929 ns36spawn take 169569 us, child_setup take 90163 us37execve, arg /bin/sh "-c" "exec /bin/cat"38execve, arg /bin/cat39...在另外一个终端下运行我们的**案例:$ otp/bin/erl2Erlang R14B04 (erts-5.8.5) 1 3 4Eshell V5.8.5 (abort with ^G)51> demo:start().6ok72> demo:start().8ok93>我们可以看到二次执行的开销差不多:vfork take 8929 nsspawn take 169569 us, child_setup take 90163 us从实验得来的数字来看:vfork需要阻塞beam.smp 8个us时间,而整个spawn下来要169ms, 其中 child_setup关闭句柄等等花了90ms, 数字无情的告诉我们这些性能杀手不容忽视。解决方案:1. 改用fork避免阻塞beam.smp, erl -env ERL_NO_VFORK 12. 减少文件句柄,如果确实需要大量的open_port让另外一个专注的节点来做。祝玩得开心!

时间: 2024-10-01 06:50:13

Erlang open_port极度影响性能的因素的相关文章

影响数据库性能的因素

论坛上的数据库爱好者们,对于数据库底层的各种细节,内幕,等待事件,隐藏参数等津津乐道,对于调整好一条SQL语句使之在查询优化器/查询引擎下能高性能运转具有巨大的满足感成功感,仿佛自己掌握了天下最有价值的真理,驾驭了天下最有难度的技术.但对于设计和开发出这个数据库系统的人来说,他们看到此情此景,只好躲在一边偷偷的笑了.那么问题来了,使用别人数据库的人被称为大师(如:OCM),那么自己写出一个数据库来的人又该称为什么呢?到底谁才是真正的高手呢? 数据库系统优化中的一些观点: "系统性能出现问题进行优

解读影响网站排名因素之链接分析

影响网站排名因素非常多,但外链却是影响网站排名的主要因素,网站排名情况如何外链占了60%,这也就是为什么那么多的站长每天如一日的坚持对网站进行外部链接建设的原因所在.或许你经常可以看到很多的网站外链数量很少,友情链接也十分的少,但排名却比你几千外链的网站要好,或许,你会十分不解,既然外链占排名因素的60%,那为什么不是外链数量多的排名好呢?其实外链的数量跟质量是不成正比的,并不是说谁的外部链接数量多,排名就好的,拼的是质不是量.下面A5站长网SEO诊断团队(http://seo.admin5.c

影响网站排名因素之用户行为

影响网站的排名因素很多,不光是外链和内容,其他也有很多这方面的因素的,如:网站用户行为对网站排名也是有直接影响的,但A5 SEO诊断优化小组在给客户诊断网站时却发现很少有站长留意这方面的因素,对用户在搜索引擎的操作及在自己网站的操作却不放在心上,殊不知,深入研究好用户的这些行为习惯 ,是可以帮助你提高网站排名的.下面A5 SEO诊断优化小组就来和大家谈一下,影响网站排名的用户行为有哪些? 一.ALEXA排名及网站流量 虽说ALEXA排名现在大家都不在重视了,已经没太多站长重视这个了,但它却也能在

Java上的try catch并不影响性能(转)

转自:http://blog.csdn.net/tao_zi7890/article/details/17584813 最近因为担心自己开发的库不稳定,会影响到接入产品的正常运行,在代码的不少地方都加了一层try catch,主要是为了避免自己的一些异常抛出导致,应用crash,捕获的异常也并没有做什么特别的处理,只是在log中输出该异常的信息.try catch多了后,就开始担心会不会影响性能,以前学C或C++的时候好像曾经被警告过要尽量少使用try catch,好像是在压栈的时候会更消耗神马

sharepoint-关于SharePoint中使用代码托管是否影响性能的问题,在线等,急!!!

问题描述 关于SharePoint中使用代码托管是否影响性能的问题,在线等,急!!! 详情是这样的 现在在SharePoint一个Web站点下有两套网站,A为原版,B为新版改版,B版需求代码托管,A则不需要,在从A切换到B的时候,我在web.config里面增加了, 当时是没有问题的,正式B版上线,但是第二天早上则出现了访问超慢. 然后我恢复了web.config,将默认网页转回A版首页,异常消失. 问题: 1.代码托管和assembly这两句话对性能是否影响很大? 2.影响网站加载速度的问题一

Android往服务器传递数据 不用框架不会影响性能吗?

问题描述 Android往服务器传递数据 不用框架不会影响性能吗? Android往服务器传递数据 不用框架不会影响性能吗?说真的 ................. 解决方案 性能开销在服务器的处理以及网络通讯,用不用框架影响不大.用httpclient足够了. 当然你用框架可能调用更简单.严格来说用了反倒性能更差. 解决方案二: 性能开销在服务器de处理以及网络通讯,用不用框架影响不大.用httpclient足够了. 解决方案三: 还是要看你的服务器需要处理的客户端数量,同时有多少客户端,然

代码-图片轮播我这样做会不会影响性能

问题描述 图片轮播我这样做会不会影响性能 js代码 HTML代码 解决方案 要是页面节点不多,实际上根本感觉不出来 .pic_big中的img标签固定高度和宽度,避免频繁变动引起reflow.

SQL Server误区30日谈 第9天 数据库文件收缩不会影响性能_MsSql

误区 #9: 数据库文件收缩不会影响性能 错误!         收缩数据库文件唯一不影响性能的情况是文件末尾有剩余空间的情况下,收缩文件指定了TruncateOnly选项.     收缩文件的过程非常影响性能,这个过程需要移动大量数据从而造成大量IO,这个过程会被记录到日志从而造成日志暴涨,相应的,还会占去大量的CPU资源.     不仅在收缩的过程中影响性能,并且在文件收缩之后同样影响应能,收缩产生的大量日志会被事务日志传送,镜像,复制能操作重复执行.而空间不够时,文件还需要填0初始化从而影

PHP __autoload()方法真的影响性能吗?_php技巧

介绍 对于php性能问题,议论最多的就是__autoload()方法,很多人提到这个方法非常影响性能.还有人说opcode也能影响到__autoload()方法,所以针对这两点我做了个测试. 最终发现__autoload方法在性能方面的影响不是很大的. 环境 PHP:5.3.9 --以fastcgi模式启动 Nginx:1.1.12 eaccelerator:0.9.6.1 .   最终发现__autoload方法在性能方面的影响不是很大的.  环境    PHP:5.3.9 --以fastcg