??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产成人精品久久久国产成人一区二区三区综
,一个色综合久久,精品视频久久久久 http://www.shnenglu.com/keigoliye/category/11700.html一切都是纸老虎 zh-cn Wed, 09 Dec 2009 13:29:16 GMT Wed, 09 Dec 2009 13:29:16 GMT 60 erlang?009-12-7日关于用其他语言实现erlang模式的聊天记?/title> http://www.shnenglu.com/keigoliye/archive/2009/12/07/102764.html暗夜教父 暗夜教父 Mon, 07 Dec 2009 15:49:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/12/07/102764.html http://www.shnenglu.com/keigoliye/comments/102764.html http://www.shnenglu.com/keigoliye/archive/2009/12/07/102764.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/102764.html http://www.shnenglu.com/keigoliye/services/trackbacks/102764.html 暗夜教父Q?你说?万连接,每个q接每秒?K包吗Q?br> 2009-12-7 22:19:49 暗夜教父(199033) en 2009-12-7 22:19:49 jack(357794482) 是后面函数执行完成之后的结果给前面的原子吗 2009-12-7 22:20:54 LinkTalk.NET(909327571) 机器配置如何Q还?万个客户端如何模拟的Q?br> 2009-12-7 22:21:41 暗夜教父(199033) 机器是AMD 双核 3200+ 2009-12-7 22:21:50 LinkTalk.NET(909327571) 另外是每个q接上的旉间隔?U,没有延迟吗? 2009-12-7 22:22:12 暗夜教父(199033) 内存?GQ操作系lubuntu 9.10 2009-12-7 22:22:53 暗夜教父(199033) 我h为的没做q种延迟 2009-12-7 22:23:04 暗夜教父(199033) 服务器和客户端都是这个配|?br> 2009-12-7 22:23:16 暗夜教父(199033) 客户端是用erlang模拟q发 2009-12-7 22:23:39 暗夜教父(199033) 不过创徏6W个连接花费了一定的旉 2009-12-7 22:24:09 暗夜教父(199033) 对哦Q这样就不是6万个一起ƈ发出来的 2009-12-7 22:24:09 LinkTalk.NET(909327571) 大概多久Q?br> 2009-12-7 22:24:19 暗夜教父(199033) 没统计时?br> 2009-12-7 22:24:42 暗夜教父(199033) q里存在问题?br> 2009-12-7 22:25:27 暗夜教父(199033) 其实q发应该?q接?/ 创徏q发的时?br> 2009-12-7 22:25:27 LinkTalk.NET(909327571) 什么问题? 2009-12-7 22:25:49 LinkTalk.NET(909327571) q个无所?br> 2009-12-7 22:26:08 LinkTalk.NET(909327571) 只要你全部连接创建好后一直保持住可以了 2009-12-7 22:26:23 暗夜教父(199033) 一直保持也不是6万同?br> 2009-12-7 22:26:32 暗夜教父(199033) 创徏q接有时?br> 2009-12-7 22:26:35 LinkTalk.NET(909327571) 6万个如果能够1k/s的保?8时的话Q非常牛g 2009-12-7 22:26:38 暗夜教父(199033) 那么发生数据也有时差 2009-12-7 22:27:53 LinkTalk.NET(909327571) 你通过什么方式做到间隔一U发一ơ数据的Q?br> 2009-12-7 22:28:32 LinkTalk.NET(909327571) sleep吗? 2009-12-7 22:29:19 LinkTalk.NET(909327571) 你有没有看一下网卡的带宽消?br> 2009-12-7 22:29:37 LinkTalk.NET(909327571) 按道理应?k * 6?= 60M/s 2009-12-7 22:30:12 LinkTalk.NET(909327571) 如果辑ֈ60M以上基本是真正的稳定的实现?万ƈ?br> 2009-12-7 22:30:34 暗夜教父(199033) client那边是我同事写的 2009-12-7 22:30:39 暗夜教父(199033) 我不知道是不是sleep 2009-12-7 22:30:52 暗夜教父(199033) 带宽消耗我q也真没?br> 2009-12-7 22:30:53 LinkTalk.NET(909327571) erlang里面好像也就只有sleep?br> 2009-12-7 22:31:06 暗夜教父(199033) 我估计不?br> 2009-12-7 22:31:52 LinkTalk.NET(909327571) 另外我怀疑当q发高了以后Qsleep会不准,真正的间隔肯定会大于sleep的时?br> 2009-12-7 22:32:50 暗夜教父(199033) 恩,实有待验证 2009-12-7 22:33:04 暗夜教父(199033) 不过只有用应用来验证?br> 2009-12-7 22:33:14 暗夜教父(199033) {项目上U了Q看看实际情?br> 2009-12-7 22:33:17 LinkTalk.NET(909327571) 嗯,呵呵 2009-12-7 22:33:24 LinkTalk.NET(909327571) 你们q个用在什么项目上马? 2009-12-7 22:33:27 LinkTalk.NET(909327571) 上面 2009-12-7 22:33:30 LinkTalk.NET(909327571) 游戏吗? 2009-12-7 22:33:31 暗夜教父(199033) 恩,游戏?br> 2009-12-7 22:34:48 LinkTalk.NET(909327571) [表情] 2009-12-7 22:34:59 暗夜教父(199033) 不过风险也很?br> 2009-12-7 22:35:15 LinkTalk.NET(909327571) Z么? 2009-12-7 22:35:24 暗夜教父(199033) 没做q?br> 2009-12-7 22:35:28 暗夜教父(199033) 没有成熟目的经?br> 2009-12-7 22:35:29 LinkTalk.NET(909327571) 呵呵 2009-12-7 22:35:32 暗夜教父(199033) 什么都有可能发?br> 2009-12-7 22:35:45 LinkTalk.NET(909327571) 传统的游戏服务器Q单台到两三万ƈ发已l很牛X?br> 2009-12-7 22:35:50 暗夜教父(199033) 未知因素太多 2009-12-7 22:36:00 暗夜教父(199033) 我估?Wq能?br> 2009-12-7 22:36:00 LinkTalk.NET(909327571) 而且gq不差的情况?br> 2009-12-7 22:36:11 LinkTalk.NET(909327571) 游戏的数据通信量比较大 2009-12-7 22:36:22 LinkTalk.NET(909327571) ?br> 2009-12-7 22:36:30 暗夜教父(199033) 没过6W是因为客L的端口基本上没了 2009-12-7 22:36:45 LinkTalk.NET(909327571) q个不会?br> 2009-12-7 22:36:51 LinkTalk.NET(909327571) 客户端端口没有关pȝ 2009-12-7 22:36:55 暗夜教父(199033) 有吧 2009-12-7 22:36:59 LinkTalk.NET(909327571) 因ؓIP不一?br> 2009-12-7 22:37:11 暗夜教父(199033) 不是。我试的时?br> 2009-12-7 22:37:15 LinkTalk.NET(909327571) 同一个IP?5535个端口的限制 2009-12-7 22:37:18 暗夜教父(199033) 6万个q接从一台机器来?br> 2009-12-7 22:37:18 LinkTalk.NET(909327571) 哦,了解 2009-12-7 22:37:23 LinkTalk.NET(909327571) ?br> 2009-12-7 22:37:54 david(258667581) 服务器端只监听一个端?应该不会有端口数限制吧? 2009-12-7 22:38:24 LinkTalk.NET(909327571) 服务器端不会 2009-12-7 22:38:50 david(258667581) 做游戏的?不是都雍和宫服务器吗 2009-12-7 22:38:55 david(258667581) 都做的服务器?br> 2009-12-7 22:39:24 暗夜教父(199033) 。。?br> 2009-12-7 22:39:32 暗夜教父(199033) 我是做测?br> 2009-12-7 22:39:36 david(258667581) 另外 如果端口socket属性设|reuse为true 是否可以过6W端口 2009-12-7 22:39:48 LinkTalk.NET(909327571) 不会 2009-12-7 22:39:53 暗夜教父(199033) 服务器端是一台机器,客户端也是一台机?br> 2009-12-7 22:39:56 LinkTalk.NET(909327571) 那个是针对不同的protocol 2009-12-7 22:40:02 暗夜教父(199033) 客户端发?W个连?br> 2009-12-7 22:40:19 暗夜教父(199033) p占用6W多个端口 2009-12-7 22:40:18 david(258667581) 不同的protocol是什么意?br> 2009-12-7 22:40:35 LinkTalk.NET(909327571) tcp ?udp 可以reuse同一个port 2009-12-7 22:41:09 LinkTalk.NET(909327571) erlang其实我只是大概的了解 2009-12-7 22:41:22 LinkTalk.NET(909327571) 我打用C#和Java模拟erlang 2009-12-7 22:41:26 david(258667581) E序a试用端口2000 tcpq?然后 E序b?000端口udp再连接另外一个程序? 2009-12-7 22:41:36 david(258667581) 模拟Q?br> 2009-12-7 22:41:40 LinkTalk.NET(909327571) ?br> 2009-12-7 22:41:47 LinkTalk.NET(909327571) 我已l用C#实现?br> 2009-12-7 22:41:47 david(258667581) 怎么模拟Q?br> 2009-12-7 22:41:59 LinkTalk.NET(909327571) 是Actor模式 2009-12-7 22:42:07 LinkTalk.NET(909327571) 自己实现消息的调?br> 2009-12-7 22:42:15 LinkTalk.NET(909327571) q有实现异步~程接口 2009-12-7 22:42:41 david(258667581) actor模式是什么意?br> 2009-12-7 22:42:59 LinkTalk.NET(909327571) 一UY件设计模?br> 2009-12-7 22:43:16 LinkTalk.NET(909327571) erlang/scala{ƈ发^台都是actor模式 2009-12-7 22:44:06 david(258667581) 不懂 2009-12-7 22:44:25 david(258667581) Z么要用c#模拟Q?br> 2009-12-7 22:44:33 LinkTalk.NET(909327571) 因ؓ我熟悉C# 2009-12-7 22:44:39 LinkTalk.NET(909327571) 也打用java模拟 2009-12-7 22:45:01 LinkTalk.NET(909327571) 同时也因为C#/Java有大量的开发h员和丰富的第三方扩展 2009-12-7 22:45:25 LinkTalk.NET(909327571) 同时也有很爽的IDE 2009-12-7 22:45:26 LinkTalk.NET(909327571) Q) 2009-12-7 22:45:42 david(258667581) ?但是感觉如果你是要测性能的话 c#的性能可能跟不上erlang?br> 2009-12-7 22:45:49 david(258667581) 用c的都会好?br> 2009-12-7 22:46:01 LinkTalk.NET(909327571) 其实erlang语言本n性能不见得高Q因为是脚本语言 2009-12-7 22:46:15 LinkTalk.NET(909327571) 高ƈ发是因ؓU消息传递,可以有效的避免死?br> 2009-12-7 22:46:27 LinkTalk.NET(909327571) 传统语言比如c/c++要避免死锁比较难 2009-12-7 22:46:49 LinkTalk.NET(909327571) l大家看老外的一个测试数?br> 2009-12-7 22:46:57 LinkTalk.NET(909327571) erlang其实是执行效率相对比较差的 2009-12-7 22:47:20 david(258667581) 哪里 erlang的性能应该是可以跟c叫板?br> 2009-12-7 22:48:04 LinkTalk.NET(909327571) http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=csharp&lang2=hipe&box=1 2009-12-7 22:48:16 LinkTalk.NET(909327571) q个里面有很多语a的性能试比较 2009-12-7 22:48:23 LinkTalk.NET(909327571) erlang是比较差的 2009-12-7 22:49:02 LinkTalk.NET(909327571) 传统语言达不到高q发是因为无法有效的避免死锁Q还有cpu调度做得不好 2009-12-7 22:50:17 暗夜教父(199033) 恩,C如果使用erlang的模?br> 2009-12-7 22:50:26 暗夜教父(199033) l对不会?br> 2009-12-7 22:50:29 LinkTalk.NET(909327571) ?br> 2009-12-7 22:50:37 LinkTalk.NET(909327571) erlang本n是C写的 2009-12-7 22:50:41 暗夜教父(199033) ?br> 2009-12-7 22:50:54 LinkTalk.NET(909327571) 我记得国内好像有个牛人在研究用C++模拟erlang 2009-12-7 22:51:00 LinkTalk.NET(909327571) 好像是盛大的一个架构师 2009-12-7 22:51:13 暗夜教父(199033) 貌似现在做linux下做服务器端得,C比C++多了 2009-12-7 22:51:20 LinkTalk.NET(909327571) ?br> 2009-12-7 22:51:29 LinkTalk.NET(909327571) linux下c?br> 2009-12-7 22:51:36 暗夜教父(199033) 我记得好像云风把大话西游的服务器端改成C?br> 2009-12-7 22:52:28 生啊牙(86753957) 51.com的服务器是用C++模拟erlang?br> 2009-12-7 22:52:50 生啊牙(86753957) 使用协程 2009-12-7 22:53:59 LinkTalk.NET(909327571) 嗯,协程可以在传l的面向q程的线E上模拟异步操作 2009-12-7 22:55:05 LinkTalk.NET(909327571) 其实高ƈ发只是一U设计模?br> 2009-12-7 22:55:19 LinkTalk.NET(909327571) erlang把这个设计模式固化ƈ强制到语法里?br> 2009-12-7 22:56:22 LinkTalk.NET(909327571) C#2.0开始有个新的特性,叫iteratorQ通过yield关键字来实现coroutineQ协E) 2009-12-7 22:56:39 LinkTalk.NET(909327571) q且在语法上也可以用q诏的Ş式来实现异步的操?br> 2009-12-7 22:56:49 LinkTalk.NET(909327571) 和erlang的Ş式类?br> 2009-12-7 22:57:10 LinkTalk.NET(909327571) java里面目前只有anonymous class可以实现异步调用 2009-12-7 22:57:44 LinkTalk.NET(909327571) 但是那个语法写v来有些牵强,花括号会嵌深 2009-12-7 22:59:19 LinkTalk.NET(909327571) 我用C#实现的actor模式也可以处理每分钟大概200万条消息Q在PC上) 2009-12-7 22:59:24 LinkTalk.NET(909327571) AMD双核 2009-12-7 23:00:28 LinkTalk.NET(909327571) 也测试过HTTP hQ大概可以达?万多q发Q不q是6U一个请求(sleep6U,实际会gq到10U以上)Qcpu占用40-60 2009-12-7 23:01:54 LinkTalk.NET(909327571) 每分?00万消息是最单的ping/pong试 2009-12-7 23:06:12 david(258667581) 以前没听说过 协程 呵呵 2009-12-7 23:06:33 LinkTalk.NET(909327571) 是否有协E无所谓的 2009-12-7 23:07:14 LinkTalk.NET(909327571) 关键是纯消息传递(避免死锁Q还有线E合理有效的调度Q实现高效的异步处理Q?br> 2009-12-7 23:07:35 david(258667581) ?关键是避开?br> 2009-12-7 23:08:04 LinkTalk.NET(909327571) q最好再能够在语法上异步操作用序化的代码来表C?br> 2009-12-7 23:08:22 LinkTalk.NET(909327571) 实在不行也无所谓,可以用event handler的方?br> 2009-12-7 23:08:48 david(258667581) 能否举一个异步操作的具体应用场景Q?br> 2009-12-7 23:09:08 LinkTalk.NET(909327571) 很多都是异步操作Q那样IO才可以做到高效) 2009-12-7 23:09:19 LinkTalk.NET(909327571) 比如epoll和windows的iocp 2009-12-7 23:09:22 LinkTalk.NET(909327571) 都是异步?br> 2009-12-7 23:09:44 LinkTalk.NET(909327571) 单的原理是调用函数递交或注册一个IOh到系l内?br> 2009-12-7 23:09:45 david(258667581) 是不是都是底层的 2009-12-7 23:09:55 LinkTalk.NET(909327571) 然后不需要阻塞,立即q回 2009-12-7 23:10:17 LinkTalk.NET(909327571) pȝIO内核收到数据或相关的事g会触发当初注册的回调函数 2009-12-7 23:10:59 LinkTalk.NET(909327571) 调用h ?数据q回或事件触?不在同一个操作系l线E上完成Q就UCؓ异步 2009-12-7 23:11:13 LinkTalk.NET(909327571) 异步的IO才比较高?br> 2009-12-7 23:11:37 LinkTalk.NET(909327571) 操作pȝ的线E数有限?br> 2009-12-7 23:11:42 david(258667581) q些都不?无论是java和c#q是cQ都已经有专门的api支撑?br> 2009-12-7 23:11:51 david(258667581) 关键是业务上的操? 2009-12-7 23:11:55 LinkTalk.NET(909327571) 一般上了千以后Q线E的效率比较差?br> 2009-12-7 23:11:58 david(258667581) 锁的都是业务 2009-12-7 23:12:02 LinkTalk.NET(909327571) 而且很耗cpu和内?br> 2009-12-7 23:12:23 LinkTalk.NET(909327571) 所以要通过合理的调度和异步操作来分享宝늚操作pȝU程 2009-12-7 23:12:51 LinkTalk.NET(909327571) 严格遵守actor模式可以有效的避免死? 2009-12-7 23:13:04 david(258667581) [表情] 2009-12-7 23:14:34 LinkTalk.NET(909327571) 我也在摸索和试Qerlang的消息调度和分布式支持是目前最好的 2009-12-7 23:14:49 LinkTalk.NET(909327571) scala也不错,twitter放弃erlang转向scala 2009-12-7 23:15:00 LinkTalk.NET(909327571) 但是scala在分布式支持斚w不及erlang 2009-12-7 23:15:30 LinkTalk.NET(909327571) 但是scala有最大的好处是ZJVMQ可以利用java的各U好?br> 2009-12-7 23:15:33 david(258667581) 分布式以后是势 所以感觉erlang的生命力应该q是很强?br> 2009-12-7 23:15:44 LinkTalk.NET(909327571) 嗯,分布式其实其他语a也可以做?br> 2009-12-7 23:16:05 LinkTalk.NET(909327571) 只是erlang已经做了十几q了 2009-12-7 23:16:19 LinkTalk.NET(909327571) 其他语言也肯定会逐渐支持?br> 2009-12-7 23:16:25 david(258667581) ?br> 2009-12-7 23:16:43 LinkTalk.NET(909327571) 但是我个人比较觉得遗憄是erlang的语法和~程模式 2009-12-7 23:17:08 LinkTalk.NET(909327571) 如果erlang代码上到一定的量以后维护和调试q当麻烦了 2009-12-7 23:17:11 david(258667581) 语法习惯了就?关键是对于结构的支持 2009-12-7 23:17:17 david(258667581) 可读性太?br> 2009-12-7 23:17:31 LinkTalk.NET(909327571) 嗯,数据l构表现力也不够丰富 2009-12-7 23:17:35 LinkTalk.NET(909327571) 都是tuple 2009-12-7 23:17:43 LinkTalk.NET(909327571) 眼睛要看׃ 2009-12-7 23:19:09 david(258667581) 开发环境也没跟?没有很好的IDE 2009-12-7 23:19:16 LinkTalk.NET(909327571) ?br> 2009-12-7 23:19:37 LinkTalk.NET(909327571) 脚本语言重构hq当麻烦了 2009-12-7 23:19:57 T.t.T!Ck.K?(121787333) 有一个老外也用C#来模拟erlang的模?br> 2009-12-7 23:20:06 LinkTalk.NET(909327571) 因ؓ无类型,无法反射元数据,没有办法自动生成文档Q更N?br> 2009-12-7 23:20:07 Lenn(28663) ERLANG跟Java一h~译态语aQ怎么成脚本语a?br> 2009-12-7 23:20:22 LinkTalk.NET(909327571) erlang严格来讲是脚?br> 2009-12-7 23:20:31 LinkTalk.NET(909327571) q型的基本都是脚本 2009-12-7 23:20:44 LinkTalk.NET(909327571) 包括php也号U支持编?br> 2009-12-7 23:20:47 LinkTalk.NET(909327571) 其实q是脚本 2009-12-7 23:21:16 Lenn(28663) bin code只有200多条指oQ属于典型的中间太语aQ效率不会比Java差多?br> 2009-12-7 23:21:34 LinkTalk.NET(909327571) ?br> 2009-12-7 23:21:48 LinkTalk.NET(909327571) 我觉得Q何东襉K有得必有?br> 2009-12-7 23:21:57 LinkTalk.NET(909327571) 一斚w太强了,比如有其他的~陷 2009-12-7 23:22:06 LinkTalk.NET(909327571) q自己的喜好和具体的应用场景了 2009-12-7 23:22:08 Lenn(28663) 囑Ş太弱 2009-12-7 23:22:47 Lenn(28663) 调试h最爽,业务惛_了基本不会编E从出错 2009-12-7 23:23:16 LinkTalk.NET(909327571) ?br> 2009-12-7 23:24:26 Lenn(28663) 我们是一个案例,用JQ)Q做的东西,现在q不停改代码QIrlang那一块,要改也只是几行一会的事情 2009-12-7 23:25:17 jack(357794482) 其实q种事情要看你对语言的处理能? 2009-12-7 23:25:20 LinkTalk.NET(909327571) ?br> 2009-12-7 23:25:35 LinkTalk.NET(909327571) google的首席架构师是搞java?br> 2009-12-7 23:25:41 LinkTalk.NET(909327571) 其实q个看具体情늚 2009-12-7 23:26:17 Lenn(28663) 用什么还有历史原因,比如新的facebook很多用Erlang 2009-12-7 23:26:33 Lenn(28663) 因ؓ做好的东西更改语a是个大问?br> 2009-12-7 23:26:36 LinkTalk.NET(909327571) 但是更新的twitter由erlang转向了scala 2009-12-7 23:26:58 LinkTalk.NET(909327571) 另外erlang十几q了Q到今天才红Q也是有一定的原因?br> 2009-12-7 23:27:13 LinkTalk.NET(909327571) erlang有非常突出的优势Q但是也存在一些不够完的地方 2009-12-7 23:29:04 Lenn(28663) 现在C也挺z跃Q业务有比较强的优势 2009-12-7 23:29:37 LinkTalk.NET(909327571) 嗯,是的Q) 2009-12-7 23:29:57 LinkTalk.NET(909327571) 所以就其他语a的开发h员也开始了?br> 2009-12-7 23:30:02 LinkTalk.NET(909327571) 学习?br> 2009-12-7 23:30:04 Lenn(28663) 囑Ş斚w却丝毫不?br> 2009-12-7 23:30:05 LinkTalk.NET(909327571) 或模拟erlang 2009-12-7 23:30:08 LinkTalk.NET(909327571) ?br> ]]> Patch Mnesia 使用TokyoCabinet引擎H破2G存储限制 http://www.shnenglu.com/keigoliye/archive/2009/09/29/97547.html暗夜教父 暗夜教父 Tue, 29 Sep 2009 07:12:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/29/97547.html http://www.shnenglu.com/keigoliye/comments/97547.html http://www.shnenglu.com/keigoliye/archive/2009/09/29/97547.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/97547.html http://www.shnenglu.com/keigoliye/services/trackbacks/97547.html 为啥要PATCHQ?/p>
Mnesia最大的~陷是存储限制。这不是数据库系l的错误Q因为Mnesia能够控制虚拟数据的大。主要的问题在于q时的Erlang DETS存储引擎Q速度慢ƈ且用的32位偏U量Q限制单文g大小?GBQ?
思\Q?/p>
乎惌?mnesia 补丁?mnesiaex 。这个东西解除了加在 mnesia 数据库系l上所有的限制(虽说上面已经提到Q实际上 mnesia 代码本n没有什么真正的限制)——你现在可以?SleepyCat/BerkeleyDB/MySQL/Amazon S3/Tokyo Cabinet/… 甚至是你自己喜欢的某U东西来当作 mnesia 的后端,像 ets/dets 一栗而访问的接口仍保持不变——l沿?mnesia 的接口,一行也不用攏V?DIY q种扩展也变得相当容易,写一?behavior 成了?/p>
实现q程
1Q与从源代码~译的方式安装Erlang
tar xvf otp_src_R12B-5.tar.gz
cd otp_src_R12B-5
./configure & make & make install
注意Q我的系l是RHEL 5.3Q默认安装目录ؓ/usr/local/erlang
2Q安装Mnesiaex
tar xvf mnesia-4.4.7.6.tar.gz
cd mnesia-4.4.7.6
./configure --prefix=/usr/local
make
make check
make install
注意Q这里一定要指定prefixQ不然就装到/usr目录M
3Q安装Tokyo Cabinet
tar xvf tokyocabinet-1.4.10.tar.gz
cd tokyocabinet-1.4.10
./configure --prefix=/usr
make & make install
3Q安装tcerl
tar xvf tcerldrv-1.3.1e.tar.gz
cd tcerldrv-1.3.1e
./configure --prefix=/usr
make & make install
tar xvf tcerl-1.3.1e.tar.gz
cd tcerl-1.3.1e
./configure --prefix=/usr/local
make & make install
本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/jimmychou/archive/2009/03/13/3988468.aspx
]]> 关于Erlang和SMP的一些说?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/24/97172.html暗夜教父 暗夜教父 Thu, 24 Sep 2009 14:23:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/24/97172.html http://www.shnenglu.com/keigoliye/comments/97172.html http://www.shnenglu.com/keigoliye/archive/2009/09/24/97172.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/97172.html http://www.shnenglu.com/keigoliye/services/trackbacks/97172.html
http://shiningray.cn/some-facts-about-erlang -and-smp.html
原文Q?a >http://groups.google.com/group/erlang -questions/browse_thread/thread/7827f5e32681ca8e
by.Kenneth Erlang /OTP team, Ericsson 译:ShiningRay
以下是一?span class=hilite1>Erlang SMP实现的细节和与性能与~性相关一些简单介l?/p>
几周之内q有有一个关于多核如何运作以及未来如何发展的更详l的介绍。我打算一些内Ҏ在我的报告中Q将??7日的ICFP2008Q?span class=hilite1>Erlang Workshop在Victoria BC展示l大家?/p>
没有SMP支持?span class=hilite1>Erlang VM只有1个运行在d理线E中的调度器。该调度器从q行队列Qrun-queueQ中取出可以q行?span class=hilite1>Erlangq程以及IOdQ而且因ؓ只有一个线E访问他们所以无锁定Q何数据?/p>
而带有SMP支持?span class=hilite1>Erlang VM可以有一个或多个调度器,每个q行在一个线E中。调度器从同一个公p行队列中取出可运行的Erlang q程和IOd。在SMP VM中所有的׃n数据l构都会由锁q行保护Q运行队列就是这样一个由锁保护的数据l构?/p>
从OTP R12B开始,如果操作pȝ报告有多?个的CPUQ或者核心)VM的SMP版本会自动启动,q且ҎCPU或者核心的数量启动同样数量的调度器?/p>
你可以从“erl”命o打印出来的第一行看到它选择了哪些参数。例如:
Erlang (BEAM) emulator version 5.6.4 [source] [smp:4] [asynch-threads:0] …..
其中“[smp:4]”表示SMP VMq行?个调度器?/code>
默认值可以用“-smp [enable|disable|auto]”来替换,auto是默认的。如果smp被启用了Q?smp enableQ,要设|调度器的数量可以?#8220;+S Number”其中Number是调度器的数量(1?024Q?/p>
注意1Q运行多于CPU或核心L的调度器不会有Q何提升?/p>
注意2Q在某些操作pȝ中一个进E可使用的CPU或者核心的数量可以被限制。例如,在Linux中,命o“taskset”可以实现这个功能?Erlang VM目前q只能探CPU或者核心的LQ不会考虑“taskset”所讄的掩码。正因如此,例如可能会出玎ͼ已经出现q了Q即?span class=hilite1>Erlang VMq行?个调度器Q也只用了2个核心。OS会进行限制因为它要考虑“taskset”所讄的掩码?/p>
每个Erlang VM的调度器都运行于一个OSU程上,是OS来决定线E是否执行在不同的核心上。一般来说OS会很好地处理q个问题q且会保证线E在执行期间q行于同一个核心上?/p>
Erlang q程会被不同的调度器q行Q因Z们是从一个公p行队列中被取出,由首先可用的调度器运行?/p>
性能和~?/h3>
只有一个调度器的SMP VM要比非SMP的VME微慢那么一点点。SMP VM内部需要用到各U锁Q不q只要不存在锁的争用Q那么由锁引L开销不会非常大(是锁争用上面需要花旉Q。这也解释了Z在某些情况下Q运行多个只有一个调度器的SMP VM要比包含多个调度器的单一SMP VM更加高效。当然运行多个VM要求应用可以按照多个q行d的方式运行ƈ且之间没有或者几乎不通讯?/p>
一个程序是否能在多怸的SMP VM中良好地q行提升很大E度上取决于E序的性质Q某些程序可以保持线性提升至8核甚?6核,同时其他某些E序基本不能提升Q连2栔R不行。实际应用中很多E序都能在主市场的核心C得到提升Q见下文?/p>
若ƈ行的持箋“通话”由每个核心一个或多个Erlang q程来表C,实际的支持大量通话的电信品已l先现出在双核和四核处理器上不俗的~性。注意,q些产品是在SMP VM和多核处理器出现很久以前按照普通的Erlang 风格来写的,他们也能无须M修改甚至不需重新~译代码p?span class=hilite1>Erlang SMP VM中获益?/p>
SMP性能得到持箋改进
SMP实现正被不断改进以便能得到更好的性能和~性。在每个服务发布版R12B-1,2,3,4,5…,R13B{等中,你都能发现新的优化?/p>
一些已知的瓉
单一的常见运行队列随着CPU或核心的数量的增加会成ؓ一个显著的瓉?/p>
q从4核开始往上就会显现出来,不过4总然可以ؓ多数应用E序提供不错的性能。我们正在从事一个每个调度器一个运行队列的解决Ҏ作ؓ目前最重要的改q?/p>
Ets表格会引入锁。在R12B-4之前在每ơ对一个ets-table的访问中会用C个锁Q但是在R12B-4中meta-table的锁被优化过Q可以显著减争用(前面已经提到争用是有很大代h的)。如果很?span class=hilite1>Erlangq程讉K同一个表|׃有很多锁争用造成性能降低其当这些进E主要工作是讉Kets-table。锁存在于表U而非记录U。注意!q也会媄响到Mnesia因ؓMnesia用到了很多ets-table?/p>
我们关于SMP的策?/h3>
当我们开始实现SMP VM的最初,我们q定了{略Q?#8220;首先让它可以q行Q然后测量,然后优化”。自?006q五月我们发布了W一个稳定的SMP VMQR11BQ以来,我们一直遵循着q个{略?/p>
q有更多已知的东西可以改q,我们会按照性能的收益大先后各个击破?/p>
我们主要的_֊攑֜多核Q大?Q上更好的连l~性上?/p>
卓越典范
即SMPpȝ有还有一些已知的瓉不过已经有不错的整体性能和~性,同时我相信在让程序员利用多核机器事半功倍方面,我们是一个卓的典范?/p>
]]> Erlang开发徏?杂记? http://www.shnenglu.com/keigoliye/archive/2009/09/24/97082.html暗夜教父 暗夜教父 Wed, 23 Sep 2009 17:00:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/24/97082.html http://www.shnenglu.com/keigoliye/comments/97082.html http://www.shnenglu.com/keigoliye/archive/2009/09/24/97082.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/97082.html http://www.shnenglu.com/keigoliye/services/trackbacks/97082.html erlang目开发中的一些记录,卛_含很多通俗易懂的原则,也包含一些似是而非的徏议,比较混ؕQ还没有U篏C个可以分门别cȝ地步Q各位就就看吧..
:) * 保没有M~译警告 * Erlang 中String采用list实现Q?2位系l中Q其1个字W用8个字节的I间Q?个保存value,
4个保存指?。因此string速度较慢Q空间占用较? * 在Server中,L力书写N归(tail-recursive)的函?
* 使用'++'Ӟleft list会被拯Q然后添加到right list的头部,因此最好把length较短的list攑֜左侧
* 避免使用regexpQ如果需要正则表辑ּQ请使用re *
timer模块的大部分函数实现Q依赖于一个processQ如果过多用timerQ会Dq个process负蝲q大Q媄响效率? 推荐使用erlang :send_after/3?span class="hilite1">erlang:start_timer/3 * 避免使用list_to_atom/1Q因?span class="hilite1">erlang中atom数量最大ؓ1048576, 且不q行GC控制。因此如果持l性的调用list_to_atom/1
可能很容易达到系l上限,从而导致emulator terminate。请使用list_to_existing_atom/1? *
list内部实现Z个列表,因此length(List), 需要遍历整个list比较耗时 *
对于不同的数据类型,使用不同的size函数Qtuple_size/1, byte_size/1, bit_size/1 * 使用binary
match来进行binary的分Ԍ而不使用split_binary/2 *
如果两个list都拥有很多数据,那么请不要?--'Q而是数据{化到ordsetsQ然后调用ordsets:substract/2. *
对于binary相关操作可以q行binary优化Qbin_opt_info~译选项Q代码框Ӟ *
f(<<Pattern1,...,Rest/bits>>,...) -> ... % Rest is
not used here f(Rest,...);
f(<<Pattern2,...,Rest/bits>>,...) -> ... % Rest is not
used here f(Rest,...); ... f(<<>>, ...)
-> ReturnValue. *
调用lists:flatten/1可以list扁^化,q个操作代h很大Q比'++'q要昂贵。下面这些时候我们可以避免: 数据发送给port?
调用list_bo_binary/1和iolist_to_binary? * 的函数可以让您方便的找出错误的函数和代?
* 不要在同一行出现相同的W号 20 some_fun() -> 21 L = [{key1, v1},
{key2, [some_record#v21, v22]}], 22 ... ~译Ӟ会提Cline 21 '[' 语法错误Q?
因ؓ21行有多个 '[' Q所以这个bug不能准确定位Q你需要花旉L查代码? 好的做法是: 20 some_fun() ->
21 L = [{key1, v1}, 22 {key2, [some_record#v21, v22]}
23 ], ... q样Q编译其会提CZ line 22 '['
语法错误Q你很开q道是那个地方错了? * 使用 CTRL Q?\ ?init:stop()Q?可以退?span class="hilite1">ErlangQ?使用CTRL Q?G ?CTRL + C 弹出菜单选项Q可以选择是否退?span class="hilite1">Erlang? 其中CTRL Q?G可以用来q接其他的shellQ?CTRL Q?C可以查看其他一些系l信?
Ctrl + C abort 是野蛮的退出方? * use "open_port({fd,0,2}, [out])" make
erlang program write standard error to unix system
* If you don't run experiments before you start designing a new system,
your entire system will be an experiment! * standard data structure
desc: Module Description sets sets, i.e. a collection of unique
elements. gb_sets sets, but based on a general balanced data structure
gb_tree a general balanced tree dict maps, also called associative
arrays ets hash tables and ordered sets (trees) dets on-disk hash tables
SuggestionQ? elments count: 0 Q?100 | 100 - 10000 | 10000 - our
select : list | ets | gb_tree * 通过code:clash/0
代码中是否有module冲突现象Qsticky) * epmd -d -d 启动 epmd 可以查看erlang node之间的通讯 *
正常的逻辑代码和错误处理代码分,发生错误Ӟ管错误。由另一个错误处理模块进行处? * cM于操作系l,我们的程序也可以分ؓkernel ?
user 两层Q?对于kernell对不能出现错误Q?对于user可以出现错误Q进行恢? *
process层loop涉及的代码及函数Q最好在一个module中实? * process 的register
name和module名称一_ 便于L代码 * 每个processh一个单一的角Ԍ比如Qsupervisor 用来q行错误恢复Q?
work 工作者,可以出现错误Q?trusted worker 不会出现错误 *
通过函数调用可以实现的功能,׃要用sever实现Q如gen_server, 及类似的loop 实现Q? *
l消息加一个tagQ在发生错误的时候,可以定位到消息,同时也有利于E序的稳? *
在消息@环中Q对于unknown的消息,误用lib:flush_receive/0 其清除Q减轻process msg queue的长? *
server中L书写N归的@? * 量使用recordQ?而不是原始的tuple来表现数据结构, 在用recordӞ使用select
matchQ? #person{name = Name, age = Age} = Person *
对于q回|最好也d一个tagQ用来说明返回值类型,或者执行成功与? * 可能少的用catch和tryQ在erlang E序中,不推荐主动捕获异常。只有当我们的逻辑特别复杂Q我们可以用throw来返回数据,使用catch来获取返回倹{?
* 当然E序与外界交互,外界数据不可靠时Q需要用catch和try * 慎重使用process dictoryQ?
当你使用get/1, put/1Ӟ你的应用会具有很大的slide effect。可以通过加入一个新的参数来保存原本需要存储到process
dictory中数? * 如果不想使自q涂,请不要用import *
使用exportӞ功能类似的接口l合在一Pq添加合理的注视Q这样你的接口更清晰Q别Z用v来更方便 * 不要书写嵌套太深的代?
* 不要书写太长的module * 不要书写太长的函? * 每行代码不能太长 * 避免使用
"_" 匿名变量Q请为每个变量选择有意义的名称Q如够某个变量暂时不使用Q请以下划线 "_" 开? * {error, enfile } enfile error in socket
是以为内linuxpȝ?ulimit 限制Q?在root下修改:ulimit -n 25000 * {error, enotconn}
表示socket已经关闭 * ?span class="hilite1">erlang开发时Q慎重用macroQ因?span class="hilite1">erlang的single
assign的缘故,同时调用某个marcoQ而macro又定义了某个变量Q可能导致badmatch错误? 比如Q?
-define(ADDLINEINFO1(F), ( begin Str1 =
lists:concat(["[Mod:", ?MODULE, " Line:", ?LINE, "]"]), Str1 ++ F
end )). -define(WARN(Log, F, D), log4erl:warn(Log,
?ADDLINEINFO(F), D)). 如果q箋使用 WARN, 会出现此错误 * erlang 中可以定义很多环境变量: ERL_MAX_ETS_TABLES 讄最大的ets数目 默认1400
ERL_MAX_PORTS erlang 最大的port数目 默认1024 *
.app文g中的start_phasesQ?选项既可以用来作为include
applications之间的同步启动,也可以用来对单个applicationq行分布启动? 序如下 包含included app:
application:start(prim_app) => prim_app_cb:start(normal, [])
=> prim_app_cb:start_phase(init, normal, []) =>
prim_app_cb:start_phase(go, normal, []) => incl_app_cb:start_phase(go,
normal, []) ok 无included app: application:start(prim_app)
=> prim_app_cb:start(normal, []) => prim_app_cb:start_phase(init,
normal, []) => prim_app_cb:start_phase(go, normal, []) ok *
M时候,都要重视函数的返回|通过match保您的预期Q如果发生错误,那么大胆的表达出来? ]]> 在MacOSX上测试Mochiweb遇到的一些问?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/24/97081.html暗夜教父 暗夜教父 Wed, 23 Sep 2009 16:59:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/24/97081.html http://www.shnenglu.com/keigoliye/comments/97081.html http://www.shnenglu.com/keigoliye/archive/2009/09/24/97081.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/97081.html http://www.shnenglu.com/keigoliye/services/trackbacks/97081.html A Million-user Comet Application with Mochiweb, Part 1
在MacOSXq_上遇到的一些问题: 一. IPv6D的问?
在MacOS下测试时报错econnrefusedQmochi-urls.txt文g的url不能用localhostQ得?27.0.0.1才行
在Erlang的邮件列表中扑ֈ了解释: We have seen the same issue with CouchDB. What
we found out is that in our case localhost was not only resolving to
127.0.0.1 (IPv4) but also ::1 (IPv6) and that http:request() would try to
connect to ::1 where no service was listening.
Erlang的http模块~省是打开IPv6模式的,当测试程序通过http模块q接localhostӞq接的地址是IPv6?:1地址Q但是mochi没有在此监听Q所以连接出?
{error,econnrefused} 解决Ҏ两种Q? 1. mochi-urls.txt中的地址都改?27.0.0.1
2.
在http:request(…)q行之前调用http:set_options([{ipv6,disabled}])Q关闭测试程序的IPv6模式Q用IPv4模式
理论上还有一U方法:让mochi服务器开启IPv6模式监听Q这个我不知道这么开Q? 参? You should teach
Yaws to listen also on IPv6 - “localhost” resolves not only to IPv4
127.0.0.1, but also to IPv6 ::1. ? q程能打开的文件描q符数量的限?
MacOSX下缺省能同时打开的文件描q符最大数?56个,使用 ulimit -a命o查看 $ ulimit -a core file
size (blocks, -c) 0 data seg size (kbytes, -d) 6144
file size (blocks, -f) unlimited max locked memory
(kbytes, -l) unlimited max memory size (kbytes, -m) unlimited
open files (-n) 256 pipe
size (512 bytes, -p) 1 stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited max user
processes (-u) 266 virtual memory (kbytes, -v)
unlimited 使用ulimit -n XXXX讄Q但最大数量还是不能超q?0240 查看内核每进E最大文件数Q? $
sysctl kern.maxfiles kern.maxfilesperproc kern.maxfiles: 12288
kern.maxfilesperproc: 10240 增大每进E最大文件数Q? $ sudo sysctl -w
kern.maxfilesperproc=20480 kern.maxfiles=22528 然后讄 $ ulimit -n
20480 注意ulimit只在每个shellH口生命周期内有效,当新开一个shell后,得再ơ设|? sysctl做的修改没有q个问题
三、调节IP端口可_不然最多只能有15K个连? ~省动态端口号?9152开始,Ҏ2000后最多可以有63K个连?
sysctl -w net.inet.ip.portrange.hifirst=2000
net.inet.ip.portrange.first=2000 ]]> ubuntu下编译安装Erlang http://www.shnenglu.com/keigoliye/archive/2009/09/18/96660.html暗夜教父 暗夜教父 Fri, 18 Sep 2009 11:12:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/18/96660.html http://www.shnenglu.com/keigoliye/comments/96660.html http://www.shnenglu.com/keigoliye/archive/2009/09/18/96660.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/96660.html http://www.shnenglu.com/keigoliye/services/trackbacks/96660.html 先要q样 apt-get install build-essential apt-get install libncurses5-dev apt-get install m4 apt-get install libssl-dev
然后要用新立得装如下库: libc6 unixodbc unixodbc-dev gcj
freeglut3-dev libwxgtk2.8-dev g++
然后下蝲源代? tar -xvf otp-src-R12B-0.tar.gz cd otp-src-R12B-0 sudo ./configure --prefix=/otp/erlang sudo make sudo make install
安装完毕Q可以rm -fr opt-src-R12B-0删除源代?
然后Ҏ/etc/profile export PATH=/opt/erlang/bin:$PATH alias ls='ls -color=auto' alias ll='ll -lht'
可以source /etc/profile一下,及时修改PATH
]]>Erlang与ActionScript3采用JSON格式q行Socket通讯 http://www.shnenglu.com/keigoliye/archive/2009/09/18/96649.html暗夜教父 暗夜教父 Fri, 18 Sep 2009 08:07:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/18/96649.html http://www.shnenglu.com/keigoliye/comments/96649.html http://www.shnenglu.com/keigoliye/archive/2009/09/18/96649.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/96649.html http://www.shnenglu.com/keigoliye/services/trackbacks/96649.html 需要下?a target=_blank>as3corelib 来ؓActionScript3处理JSON codec server.erl
- module(server). - export([start / 0 ,start / 1 ,process / 1 ]). - define(defPort, 8888 ). start() -> start( ? defPort). start(Port) -> case gen_tcp:listen(Port, [binary, {packet, 0 }, {active, false }]) of {ok, LSock} -> server_loop(LSock); {error, Reason} -> exit({Port,Reason}) end. %% main server loop - wait for next connection, spawn child to process it server_loop(LSock) -> case gen_tcp:accept(LSock) of {ok, Sock} -> spawn( ? MODULE,process,[Sock]), server_loop(LSock); {error, Reason} -> exit({accept,Reason}) end. %% process current connection process(Sock) -> Req = do_recv(Sock), io:format( " ~p~n " , [Req]), {ok, D, []} = rfc4627:decode(Req), {obj, [{ " name " , _Name}, { " age " , Age}]} = D, Name = binary_to_list(_Name), io:format( " Name: ~p, Age: ~p~n " , [Name, Age]), Resp = rfc4627:encode({obj, [{ " name " , ' Hideto2 ' }, { " age " , 24 }]}), do_send(Sock,Resp), gen_tcp:close(Sock). %% send a line of text to the socket do_send(Sock,Msg) -> case gen_tcp:send(Sock, Msg) of ok -> ok; {error, Reason} -> exit(Reason) end. %% receive data from the socket do_recv(Sock) -> case gen_tcp:recv(Sock, 0 ) of {ok, Bin} -> binary_to_list(Bin); {error, closed} -> exit(closed); {error, Reason} -> exit(Reason) end.
Person.as
package { public class Person { public var name:String; public var age: int ; public function Person() { } } }
Client.as
package { import com.adobe.serialization.json.JSON; import flash.display.Sprite; import flash.events. * ; import flash.net.Socket; import flash.text. * ; public class Client extends Sprite { private var socket:Socket; private var myField:TextField; private var send_data:Person; public function Client() { socket = new Socket(); myField = new TextField(); send_data = new Person(); send_data.name = " Hideto " ; send_data.age = 23 ; socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData); socket.connect( " localhost " , 8888 ); socket.writeUTFBytes(JSON.encode(send_data)); socket.flush(); myField.x = 20 ; myField.y = 30 ; myField.text = " test " ; myField.autoSize = TextFieldAutoSize.LEFT; addChild(myField); } private function onSocketData(event:ProgressEvent): void { while (socket.bytesAvailable) { var recv_data: * = JSON.decode(socket.readUTFBytes(socket.bytesAvailable)); myField.text = " Name: " + recv_data.name + " , age: " + recv_data.age.toString(); } } } }
q行Erlang服务器端Q?br>
Eshell > c(server). Eshell > server:start(). " {\ " name\ " :\ " Hideto\ " ,\ " age\ " :23} " Name: " Hideto " , Age: 23
q里打印ZErlang Socket Server接收到的AS3 Client发过来的JSON decodeq的一个person对象 q行AS3客户端: client.html上首先显C?#8220;test”Q然后异步处理完Socket消息发送和接受后,decode Erlang Server端发q来的person对象Q将面上的TextField替换?#8220;Name: Hideto2, age: 24”
]]> Erlang的JSON?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/18/96647.html暗夜教父 暗夜教父 Fri, 18 Sep 2009 07:38:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/18/96647.html http://www.shnenglu.com/keigoliye/comments/96647.html http://www.shnenglu.com/keigoliye/archive/2009/09/18/96647.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/96647.html http://www.shnenglu.com/keigoliye/services/trackbacks/96647.html http://www.lshift.net/blog/2007/02/17/json-and-json-rpc-for-erlang 该JSON库采?a target=_blank>Joe Armstrong prefered Data type mapping 卻I
JSON Obj = type obj() = {obj, [ {key(), val()} ]} JSON Array = type array() = [val()] JSON Number = type num() = int () | float () JSON String = type str() = bin() JSON true false null = true , false null (atoms) With Type val() = obj() | array() | num() | str() | true | false | null and key() being a str(). (Or a binary or atom, during JSON encoding.)
试如下Q?
Eshell V5. 6.3 (abort with ^ G) 1 > O = rfc4627:encode( {obj, [ {name, hideto} , {age, 23 } ]} ). " {\ " name\ " :\ " hideto\ " ,\ " age\ " :23} " 2 > rfc4627:decode(O). {ok, {obj,[ { " name " , << " hideto " >> } , { " age " , 23 } ]} ,[]} 3 > A = rfc4627:encode([ 1 , 2 , 3 , 4 , 5 ]). " [1,2,3,4,5] " 4 > rfc4627:decode(A). {ok,[ 1 , 2 , 3 , 4 , 5 ],[]} 5 > N = rfc4627:encode( 12345 ). " 12345 " 6 > rfc4627:decode(N). {ok, 12345 ,[]} 7 > S = rfc4627:encode( " 12345 " ). " [49,50,51,52,53] " 8 > rfc4627:decode(S). {ok, " 12345 " ,[]} 9 > T = rfc4627:encode( true ). " true " 10 > rfc4627:decode(T). {ok, true ,[]} 11 > F = rfc4627:encode( false ). " false " 12 > rfc4627:decode(F). {ok, false ,[]} 13 > Null = rfc4627:encode( null ). " null " 14 > rfc4627:decode(Null). {ok, null ,[]}
]]> Flash Socket ?Erlang Socket 通信的注意事?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/18/96634.html暗夜教父 暗夜教父 Fri, 18 Sep 2009 04:40:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/18/96634.html http://www.shnenglu.com/keigoliye/comments/96634.html http://www.shnenglu.com/keigoliye/archive/2009/09/18/96634.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/96634.html http://www.shnenglu.com/keigoliye/services/trackbacks/96634.html 转自http://www.javaeye.com/topic/401041 学erlang有一D|间了Q现在在l护一套webimpȝ q打扩展成 webgame 的服务程?/p>
在没有用包协议的时候,遇到好多_包问题Q实在恼?/p>
查阅了相兌料:
Flash Socket ?writeUTF() 会自动增加包头长度的协议Q刚好对应了 Erlang的Socket选项 {packet,2} q得两者的通信非常完美Q再也不用担心粘包什么的问题?/p>
下面是我写的一个Flash Socket 接口QSocketBridge.as
package { import flash.display.Sprite; import flash.events. * ; import flash.net.Socket; import flash.utils. * ; import flash.external.ExternalInterface; import flash.system. * ; public class SocketBridge extends Sprite { Socket.prototype.timeout = 3000 ; private var socket:Socket; public function SocketBridge() { socket = new Socket(); socket.addEventListener( Event.CONNECT, onConnect ); socket.addEventListener( ProgressEvent.SOCKET_DATA, onDataRecevice); socket.addEventListener( Event.CLOSE, onClose); socket.addEventListener( IOErrorEvent.IO_ERROR, onError); if (ExternalInterface.available) { ExternalInterface.addCallback( " socket_connect " ,socket_connect); ExternalInterface.addCallback( " socket_send " ,socket_send); ExternalInterface.addCallback( " load_policy " ,load_policy); } } public function onError(e): void { ExternalInterface.call( " sb_onerror " ,e.text); socket.close(); } public function load_policy(host:String,port): void { Security.loadPolicyFile( " xmlsocket:// " + host + " : " + port); } public function socket_connect(host:String,port): void { try { socket.connect(host,port); } catch (e) { ExternalInterface.call( " sb_onerror " ,e.text); } } public function socket_send(msg:String) { socket.writeUTF(msg); socket.flush(); } private function onConnect(event:Event): void { ExternalInterface.call( " sb_onconnect " , true ); } private function onClose(event:Event): void { socket.close(); ExternalInterface.call( " sb_onclose " , true ); } private function onDataRecevice( eventrogressEvent ): void { var sdata:String; while (socket.bytesAvailable) { sdata = socket.readUTF(); ExternalInterface.call( " sb_ondata " ,sdata); } } } }
]]> erlang|络~程的几个性能调优和注意点 http://www.shnenglu.com/keigoliye/archive/2009/09/14/96106.html暗夜教父 暗夜教父 Mon, 14 Sep 2009 04:25:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/14/96106.html http://www.shnenglu.com/keigoliye/comments/96106.html http://www.shnenglu.com/keigoliye/archive/2009/09/14/96106.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/96106.html http://www.shnenglu.com/keigoliye/services/trackbacks/96106.html 前些天给echo_server写了个非常简单的q接压力试E序,
1 . - module(stress_test). 2 . 3 . - export([start / 0 , tests / 1 ]). 4 . 5 . start() -> 6 . tests( 12345 ). 7 . 8 . tests(Port) -> 9 . io:format( " starting~n " ), 10 . spawn(fun() -> test(Port) end), 11 . spawn(fun() -> test(Port) end), 12 . spawn(fun() -> test(Port) end), 13 . spawn(fun() -> test(Port) end). 14 . 15 . test(Port) -> 16 . case gen_tcp:connect( " 192.168.0.217 " , Port, [binary,{packet, 0 }]) of 17 . {ok, _} -> 18 . test(Port); 19 . _ -> 20 . test(Port) 21 . end.
一开始我的这个stress_test客户端运行在windows上面, echo_server服务器端q行在linux上面?
l果接受?016个连接就停止? 于是我用ulimit -n 改了服务器端的文件描q符数量?0240.
接着q是如此,折腾了几?最l还是没有搞明白?
于是求助于公司的linux~程牛h,l果让我一?.. 客户端没有修Ҏ件描q符个数. windows上得在注册表里面?
牛h开始对q东西的性能感兴了,刚好我摸了一阵子erlang的文?于是我俩p向了erlang|络q接的性能调优之旅啦~~q程真是让h兴奋?我们很快通过?024q一关~~C4999个连?很兴?
但ؓ什?999个连接呢, 查一下代码终于发现echo_server.erl定义了一个宏, 最大连接数?000. 我又倒~~
修改~译之后, q接数跑?01xx多了, 太哈皮了!
再测102400个连接时,?2767个连接数erl挂了~说是q程开得太多了. 好在记得q个erl的参?P,可以定义erlang能生成的q程? 默认?2768. 改了!
后面不知怎么着,?1231个连接停止了. 新的性能瓉又卡了我? 好在牛h对linux? 用strace(q东西会莫名地退?,
stap查出一些苗?
我也惛_在otp文档好像提过另一个limit,那就是端口数...在此同时我们发现erlang在linux上是用的传统poll模型.
但查erlang的源代码发现是支持epoll? 在网上搜了半?l于搜到了个maillist的帖?
代码
$./configure --enable-kernel-poll
׃我们的测试服务器是双核的,我们在配|的时候也打开了smp支持. Ƣ快的make & make install之后....
?/proc/sys/net/ipv4/ip_local_port_range 的内Ҏ成了1024?5535. 最多也也能Ҏ65535 :)
代码
$echo 1024 65535 > ip_local_port_range
另外再添加一个erl的环境变?br>
代码
$export ERL_MAX_PORTS= 102400
于是开始跑?不过q次跑不一样了
echo_server
$erl -noshell +P 102400 +K true +S 2 -smp
-s echo_server start
stress_test
$erl -noshell +P 102400 +K true +S 2 -smp
-s stress_test start
q里?K true,表示使用内核poll,+S 2 表示两个?
q样可欢快啦~~~ 10w大关q咯! 而且比刚才没用epoll的速度快暴多~~
于是我们又开始了204800个连接发试了~~~
用top一看cpu占用率极?服务器只?%左右?内存也不是很大~~
]]>echo_server http://www.shnenglu.com/keigoliye/archive/2009/09/14/96105.html暗夜教父 暗夜教父 Mon, 14 Sep 2009 04:24:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/14/96105.html http://www.shnenglu.com/keigoliye/comments/96105.html http://www.shnenglu.com/keigoliye/archive/2009/09/14/96105.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/96105.html http://www.shnenglu.com/keigoliye/services/trackbacks/96105.html
1 . - module(echo_server). 2 . - export([start / 0 ,stop / 0 ]). 3 . 4 . - define(LISTEN_PORT, 12345 ). % 开攄?nbsp; 5 . - define(MAX_CONN, 5000 ). % 最大连接数 6 . 7 . start() -> 8 . process_flag(trap_exit, true ), % 讄退出陷?nbsp; 9 . tcp_server:start_raw_server( ? LISTEN_PORT, 10 . fun(Socket) -> socket_handler(Socket,self()) end, 11 . ? MAX_CONN, 12 . 0 ). 13 . 14 . %% 处理数据 15 . socket_handler(Socket,Controller) -> 16 . receive 17 . {tcp, Socket, Bin} -> 18 . gen_tcp:send(Socket, Bin); % echo 19 . {tcp_closed, Socket} -> 20 . ok; 21 . _ -> 22 . socket_handler(Socket,Controller) 23 . end. 24 . 25 . stop() -> 26 . tcp_server:stop( ? LISTEN_PORT).
ZJoe Armstrong 的tcp_server模块来做? 试试?:)
~译
erl -noshell -s make all -s init stop
q行
erl -noshell -sname coderplay -s echo_server start
]]> erlang |络调优实战 http://www.shnenglu.com/keigoliye/archive/2009/09/14/96096.html暗夜教父 暗夜教父 Mon, 14 Sep 2009 03:20:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/14/96096.html http://www.shnenglu.com/keigoliye/comments/96096.html http://www.shnenglu.com/keigoliye/archive/2009/09/14/96096.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/96096.html http://www.shnenglu.com/keigoliye/services/trackbacks/96096.html erlang |络 ~程 的几个性能调优 和注意点
原文作者:coderplay
前些天给echo_server写了个非常简单的q接压力试E序,
下蝲 : stress_test.erl
- module ( stress_test ) .
- export ([ start / 0 , tests / 1 ]) .
start () ->
tests ( 12345 ) .
tests ( Port ) ->
io : format ( " starting~n " ) ,
spawn ( fun () -> test ( Port )
end ) ,
spawn ( fun () -> test ( Port )
end ) ,
spawn ( fun () -> test ( Port )
end ) ,
spawn ( fun () -> test ( Port )
end ) .
test ( Port ) ->
case
gen_tcp : connect ( " 192.168.0.217 " , Port , [ binary ,{ packet , 0 } ])
of
{ ok , _ } ->
test ( Port ) ;
_ ->
test ( Port )
end .
一开始我的这个stress_test客户端运行在windows 上面,echo_server服务器端q行在linux上面。结果接受了1016个连接就停止? 于是我用ulimit -n改了服务器端?span onclick="tagshow(event)" class="t_tag">文g描述W数量ؓ10240. 接着q是如此,折腾了几?最l还是没有搞明白?br>
于是求助于公司的linux~程牛h,l果让我一?#8230; 客户端没有修Ҏ件描q符个数. windows上得在注册表里面?
牛h开始对q东西的性能感兴了,刚好我摸了一阵子erlang?span onclick="tagshow(event)" class="t_tag">文档,于是我俩p向了erlang|络q接的性能调优之旅啦~~q程真是让h兴奋?我们很快通过?024q一关~~C4999个连?很兴?
但ؓ什?999个连接呢, 查一下代码终于发现echo_server.erl定义了一个宏, 最大连接数?000. 我又倒~~
修改~译 之后, q接数跑?01xx多了, 太哈皮了!
再测102400个连接时,?2767个连接数erl挂了~说是q程 开得太多了. 好在记得q个erl的参?P,可以定义erlang能生成的q程? 默认?2768. 改了!
后面不知怎么着,?1231个连接停止了. 新的性能瓉又卡了我? 好在牛h对linux?
用strace(q东西会莫名地退?,stap查出一些苗?我也惛_在otp文档好像提过另一个limit,那就是端口数…在此同时我们发现
erlang在linux上是用的传统poll模型.但查erlang的源代码发现是支持epoll?
在网上搜了半?l于搜到了个maillist的帖?
$./configure --enable-kernel-poll
׃我们的测试服务器是双核的,我们在配|的时候也打开了smp支持. Ƣ快的make & make install之后….
?/proc/sys/net/ipv4/ip_local_port_range 的内Ҏ成了1024?5535. 最多也也能Ҏ65535
$echo 1024 65535 > ip_local_port_range
另外再添加一个erl的环?span onclick="tagshow(event)" class="t_tag">变量
$export ERL_MAX_PORTS=102400
于是开始跑?不过q次跑不一样了
echo_server
$erl -noshell +P 102400 +K true +S 2 -smp -s echo_server start
stress_test
$erl -noshell +P 102400 +K true +S 2 -smp -s stress_test start
q里?K true,表示使用 内核poll,+S 2 表示两个? q样可欢快啦~~~ 10w大关q咯! 而且比刚才没用epoll的速度快暴多~~
于是我们又开始了204800个连接发试了~~~
用top一看cpu占用率极?服务器只?%左右。内存也不是很大~~ ]]>ErLang语法提要 http://www.shnenglu.com/keigoliye/archive/2009/09/11/95894.html暗夜教父 暗夜教父 Fri, 11 Sep 2009 03:04:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/11/95894.html http://www.shnenglu.com/keigoliye/comments/95894.html http://www.shnenglu.com/keigoliye/archive/2009/09/11/95894.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/95894.html http://www.shnenglu.com/keigoliye/services/trackbacks/95894.html ErLang的注释用%开头。ErLang用下划线“_”表示L变量Q类gJava的switch语法里面的default选项? ErLangp于PrologQ不q,我觉得,ErLang语法和Haskell语法比较象,都是采用 -> 定义函数? ErLang语句中的标点W号用法很象文章的标点符受? 整个函数定义l束用一个句?#8220;.”Q同一个函CQƈ列的逻辑分支之间Q用分号“;”分界Q顺序语句之_用逗号“,”分隔? ErLang中,{ }不是表示E序块的开头和l尾Q而是表示一U特D的数据l构cd——TupleQ元l)Q比如,{12, 3, ok}。我们可以把Tuple理解为定长数l? [ ] 则表C最基本的函数式~程的数据结构类型——List。List数据l构很基本,写法和用法也有一定的复杂度,不是表面上看h那么单,后面讲解Closure的章节会详细介绍List的最基本的构造原理? 下面我们来看一个简单的例子? 我们首先定义一个最单的函数Q把一个参C?0Q然后加1? times10( Number ) –> Temp = 10 * Number, Temp + 1. Z说明问题Q上面的代码把乘法操作和加法操作分成两个步骤。Temp = 10 * Number语句后面是逗号Q因是两条顺序执行的语句。Temp + 1语句后面是句P表示整个函数定义l束。而且Q可以看出,ErLang没有return语句Q最后执行的那条语句的执行结果就是返回倹{? 下面Q我们把q个函数优化一下。当参数{于0的时候,直接q?Q否则,׃?0Q然后加1Q然后返回。这时候,我们p用到case of逻辑分支语句Q相当于java的switch语句? times10( Number ) –> case Number of 0 -> 1; _ -> Temp = 10 * Number, Temp + 1 end. 我们来仔l观察这DErLangE序? 当Number{于0的时候,直接q回1。由于这是一条分支语句,和后面的分支是ƈ列的关系Q所以,1的后面的标点W号是分受后面这个分支,下划U?#8220;_”表示M其它|q里pC除?之外的Q何其它数倹{? 需要注意的一ҎQcase of语句需要用endl尾Qend之前不需要有标点W号? 上述代码中的case of 语句Q其实就是Pattern Match的一U。ErLang的Pattern Match很强大,能够大幅度简化程序逻辑Q后面进行专门介l? Pattern Match Pattern Match主要有两个功能——比较分z֒变量赋倹{? 其中Q比较分z是最主要的功能。比较分z意思是Q根据参数D行条件分支的分派。可以把比较分派功能看作是一U类gif, else{条件分支语句的z强大写法? 上面的例子中Qcase Number of 是ҎNumber的D行比较分z。更常见的写法是Q可以把Pattern Match部分提到函数定义分支的高度。于是,上述代码可以写成下面的Ş式: times10( 0 ) –> 1; times10( Number ) –> Temp = 10 * Number, Temp + 1. q段代码׃个函数定义分支构成,׃两个函数分支的函数名相同Q而且参数个数相同Q而且两个函数定义分支之间采用分号“;”分隔Q说明这是同一个函数的定义。函数式~程语言中,q种定义方式很常见,看v来Ş式很整齐Q宛如数学公式? q段代码的含义是Q当参数值等?的时候,那么Q程序走W一个函数定义分支(卛_?#8220;;”l尾?#8220;times10( 0 ) –> 1;”Q,否则Q走下面的函数定义分支(?#8220;times10( Number ) –>…”Q? W二个分支中的参C是一个常敎ͼ而是一个变量NumberQ表C个分支可以接受Q何除?之外的参数|比如Q???2{等Q这些值将赋给变量Number? 因此Q这个地方也体现了Pattern Match的第二个功能——变量赋倹{? Pattern Match的Ş式可以很复杂Q下面D几个典型的例子? Q?Q数据结构拆解赋? 前面到了ErLang语言有一U相当于定长数组的TuplecdQ我们可以很方便地根据元素的位置q行q行赋倹{比如, {First, Second} = {1, 2} 我们q可以对复合Tuple数据l构q行赋|比如 {A, {B, C}, D} = { 1, {2, 3}, 4 } List数据l构的赋g是类伹{由于List的写法和用法不是那么单,三言两语也说不清楚,q徒增困扎ͼq里不再赘述? Q?QassertEquals语句 在Java{语a中,我们写单元测试的时候,会写一些assert语句Q验证程序运行结果。这些assert语句通常是以API的方式提供,比如QassertTrue()、assertEquals(){? 在ErLang中,可以用简单的语句辑ֈcM于assertTrue()、assertEquals(){API的效果? 比如QErLang中,true = testA() q样的语句表CtestA的返回结果必LtrueQ否则就会抛出异常。这个用法很巧妙。这里解释一下? 前面讲过QErLang语法U定Q小写字母开头的名字Q都是常量名。这里的true自然也是一个常量,既然是常量,我们不可能对它赋|那么true = testA()的意思就不是赋|而是q行匚w比较? Q?Q匹配和赋值同时进? 我们来看q样一D代码? case Result of {ok, Message} -> save(Message); {error, ErrorMessage} -> log(ErrorMessage) end. q段代码中,Result是一个TuplecdQ包含两个元素,W一个元素表C成功(okQ或者失败(errorQ,W二个元素表C具体的信息? 可以看到Q这两个条g分支中,同时出现了常量和变量。第一个条件分支中的ok是常量,Message是变量;W二个条件分支中的error是常量,ErrorMessage是变量? q两个条件分支都既有比较判断Q也有变量赋倹{首先,判断ResultTuple中的W一个元素和哪一个分支的W一个元素匹配,如果盔RQ那么把ResultTuple中的W二个元素赋l这个分支的W二个变量元素。即Q如果Result的第一个元素是okQ那么走W一个条件分支,q且把Result的第二个元素赋给Message变量Q如果Result的第二个元素是errorQ那么走W二个条件分支,q且把Result的第二个元素赋给ErrorMessage变量? 在Java{语a中,实现上述的条件分支逻辑Q则需要多写几条语句ErLang语法可以从Ş式上化和简化逻辑分支分派复杂的程序? 除了支持数相{比较,Pattern Matchq可以进行范围比较、大比较等Q需要用到关键字whenQ不q用到when的情况,比if elsez不了多,q里不再赘述? 匿名函数 ErLang允许在一个函C内部定义另一个匿名函敎ͼq是函数式编E的最基本的功能。这P函数式语a才可以支持Closure。我们来看一个ErLang的匿名函数的例子? outer( C ) –> Inner = fun(A, B) -> A + B + C end, Inner(2, 3). q段代码首先定义了一个命名函数outerQ然后在outer函数内部定义了一个匿名函数。可以看刎ͼq个匿名函数采用关键字fun来定义。前面讲q,函数式编E的函数q当于面向对象~程的类实例对象Q匿名函数自然也是这P也相当于cd例,我们可以把这个匿名函数赋l一个变量InnerQ然后我们还可以把这个变量当作函数来调用Q比如,Inner(2, 3)? fun是ErLang用来定义匿名函数的关键字。这个关键字很重要。fun定义匿名函数的用法不是很复杂Q和命名函数定义cM? 函数分支的定义也是类|只是需要用endl尾Q而不是用句号“.”l尾Q而且fun只需要写一ơ,不需要向命名函数那样Q每个分支都要写。比如, MyFunction = fun(0) -> 0; (Number) -> Number * 10 + 1 end, MyFunction(3), 函数作ؓ变量 匿名函数可以当作对象赋给变量Q命名函数同样也可以赋给变量。具体用法还是需要借助重要的fun关键字。比如, MyFunction = fun outer / 1 可以把上述定义的outer函数赋给MyFunction变量。后面的 / 0表示q个outer函数只有一个参数。因为ErLang允许有多个同名函数的定义Q只要参CC同,是不同的函数? 我们可以看到QQ何函数都可以作ؓ变量Q也可以作ؓ参数和返回g来传去,q些变量也可以随时作为函数进行调用,于是具有了一定的动态性? 函数的动态调? ErLang有一个apply函数Q可以动态调用某一个函数变量? 基本用法?apply( 函数变量Q函数参数列?)。比如,上面的MyFunciton函数变量Q就可以q么调用Qapply( MyFunction, [ 5 ])? 那么我们能否Ҏ一个字W串作ؓ函数名获取一个函数变量呢Q这h们就可以Ҏ一个字W串来动态调用某个函C? ErLang中,做到q一点很单。前面讲q,函数名一旦定义了Q自然就固定了,q也cM于常量名Q属于不可变的atomQ原子)。所有的atom都可以{换成字符Ԍ也可以从字符串{换过来。ErLang中的字符串实质上都是List。字W串和atom之间的{换通过list_to_atom和atom_to_list来{换? 于是我们可以q样获取MyFuncitonQMyFunction = list_to_atom(“outer”) 如果outer函数已经定义Q那么MyFucntionq于outer函数Q如果outer函数没有定义Q那么list_to_atom(“outer”)会生一个新的叫做outer的atomQMyFucntionq于这个新产生的atom? 如果需要强制生一个已l存在的atomQ那么我们需要调用list_to_existing_atom转换函数Q这个函C会生新的atomQ而是q回一个已l存在了的atom? Tuple作ؓ数据成员集合 前面讲解函数式编E特性的时候,提到了函数式~程没有面向对象~程的成员变量,q是一个限制? ErLang的Tuplecd可以一定程度克服这个限制。Tuple可以一定程度上担当容纳成员变量的职责? 面向对象的类定义Q其实就是一数据和函数的集合,只是集合的成员之间都有一个this指针相关联,可以怺扑ֈ? ErLang的Tuplecd是数据的集合,可以很自然地发挥成员变量的作用,比如Q{Member1, Member2}? 读者可能会_ErLang的函C可以作ؓ变量Q也可以攑ֈTuple里面Q比如, { Memer1, Member2, Funtion1, Function2}。这不就和面向对象编E一样了吗? 遗憾的是Q这样做是得不偿q。因为函数式~程没有面向对象的那U内在的this指针支持Q自然也没有内在的多态和l承支持Q硬把数据和函数p合在一个Tuple里面Q一点好处都没有Q而且q׃函数作ؓ实例对象的灵zL? 所以,函数式编E的最佛_践(Best PracticeQ应该是QTuple用来容纳成员数据Q函数操作Tuple。Tuple定义和函数定义加在一P构成了松散的数据结构,功能上类g面向对象的类定义。Tuple + 函数的数据结构,h多态的Ҏ,因ؓ函数本n能够作ؓ变量替换Q但是不hl承的特性,因ؓ没有this指针的内在支持? 正是因ؓTuple在数据类型构造方面的重大作用Q所以,ErLang专门引入了一U叫做Record的宏定义Q可以对Tuple的数l下标位|命名。比如,把第一个元素叫做AddressQ第二个元素叫做ZipcodeQ这L序员可以这些名字访问Tuple里面的元素,而不需要按照数l下标位|来讉K? Tuple和Record的具体用法还是有一定复杂度Q限于篇q,本章没有展开说明Q只提了一些原理方面的要点? 其它 ErLangq有其它语法Ҏ和l节Q不再一一赘述。有兴趣的读者,可以自行去ErLang|站Qwww.erlang.orgQ进行研I?
]]>Erlang入门Q五Q——补?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/11/95888.html暗夜教父 暗夜教父 Fri, 11 Sep 2009 02:16:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/11/95888.html http://www.shnenglu.com/keigoliye/comments/95888.html http://www.shnenglu.com/keigoliye/archive/2009/09/11/95888.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/95888.html http://www.shnenglu.com/keigoliye/services/trackbacks/95888.html 1。Erlang的保留字有:
after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor
基本都是些用于逻辑q算、位q算以及Ҏ表达式的W号2.Erlang的类?/span>Q除了在前面入门一提到的类型外Q还包括Q?br>1)BinaryQ用于表C某D|知类型的内存区域 比如Q?br>1> <<10,20>>. <<10,20>> 2> <<"ABC">>. <<65,66,67>> 2QReferenceQ通过调用mk_ref/0产生的运行时的unique term 3)StringQ字W串QErlang中的字符串用双引号包括v来,其实也是list。编译时期,两个邻近的字W串被q接hQ比?string" "42" {h?"string42" 4)RecordQ记录类型,与c语言中的structcMQ模块可以通过-record属性声明,比如Q?br>-module(person). -export([new/2]). -record(person, {name, age}). new(Name, Age) -> #person{name=Name, age=Age}. 1> person:new(dennis, 44). {person,dennis,44} 在编译后其实已经被{化ؓtuple。可以通过Name#person.name来访问Name Record的name属性?br>3.模块的预定义属?/span>Q?br>-module(Module).
声明模块名称Q必M文g名相?br>-export(Functions).
指定向外界导出的函数列表-import(Module,Functions).
引入函数Q引入的函数可以被当作本地定义的函数使用-compile(Options).
讄~译选项Q比如export_all -vsn(Vsn). 模块版本Q设|了此项Q可以通过beam_lib:version/1
获取此项信息 可以通过-include?include_lib来包含文Ӟ两者的区别是include-lib不能通过l对路径查找文gQ而是在你当前Erlang的lib目录q行查找?br>4.try表达?/span>Qtry表达式可以与catchl合使用Q比如:
try Expr catch throw:Term -> Term; exit:Reason -> {'EXIT',Reason} error:Reason -> {'EXIT',{Reason,erlang:get_stacktrace()}} end 不仅如此Qtryq可以与afterl合使用Q类似java中的try..finallyQ用于进行清除作用,比如Q?br>termize_file(Name) -> {ok,F} = file:open(Name, [read,binary]), try {ok,Bin} = file:read(F, 1024*1024), binary_to_term(Bin) after file:close(F) end.5.列表推断 QList ComprehensionsQ,函数式语aҎ之一QErlang中的语法cMQ?br>[Expr || Qualifier1,...,QualifierN] Expr可以是Q意的表达式,而Qualifier是generator或者filter。还是各举例子说明下?br>1> [X*2 || X <- [1,2,3]]. [2,4,6] 2> L=[1,2,3,4,5,6,7]. [1,2,3,4,5,6,7]
3> [X|X<-L,X>=3]. [3,4,5,6,7]
再看几个比较L例子Q来自Programming Erlang Q?br>比如快速排?/span>Q?br>-module(qsort). -export([qsort/1]). qsort([])->[]; qsort([Pivot|T])-> qsort([X||X<-T,X
6.?/span>Q定义常量或者函数等{,语法如下Q?br>
-define(Const, Replacement).
-define(Func(Var1,...,VarN), Replacement).
使用的时候在宏名前加个问PQ比?ConstQReplacement插入宏出现的位|。系l预定义了一些宏:
?MODULE 表示当前模块?br>
?MODULE_STRING 同上Q但是以字符串Ş?br>
?FILE 当前模块的文件名
?LINE 调用的当前代码行?br>
?MACHINE 机器?br>
Erlang的宏与C语言的宏很相|同样有宏指示W,包括Q?br>
-undef(Macro).
取消宏定?br>
-ifdef(Macro).
当宏Macro有定义的时候,执行以下代码
-ifndef(Macro).
同上Q反?br>
-else.
接在ifdef或者ifndef之后Q表CZ满前者条件时执行以下代码
-endif.
ifl止W?/dd> 假设?define(Square(X),X*X).用于计算qxQ那??X返回X表达式的字符串Ş式,cMC语言?arg
一个简单的宏例子:
ruby 代码
- module (macros_demo).
-ifdef(debug).
-define(LOG(X), io:format ( "{~p,~p}: ~p~n" , [?MODULE,?LINE,X])).
-else .
-define(LOG(X), true ).
-endif.
-define(Square(X),X*X).
-compile(export_all).
test()->
A=3,
?LOG(A),
B=?Square(A),
io:format ( "square(~w) is ~w~n" ,[A,B]).
当编译时不开启debug选项的时候:
17> c(macros_demo).
{ok,macros_demo}
18> macros_demo:test().
square(3) is 9
当编译时开启debug之后Q?br>
19> c(macros_demo,{d,debug}).
{ok,macros_demo}
20> macros_demo:test().
{macros_demo,11}: 3
square(3) is 9
ok
可以看到LOG的输ZQ行数、模块名以及参数
7?span style="FONT-WEIGHT: bold">Process Dictionary Q每个进E都有自qprocess dictionaryQ用于存储这个进E内的全局变量Q可以通过下列
BIFs操作Q?br>
put(Key, Value)
get(Key)
get()
get_keys(Value)
erase(Key)
erase()
8、关于分布式~程 Q需要补充的几点
1Q节点之间的q接默认是transitiveQ也是当节点Aq接了节点BQ节点Bq接了节点CQ那么节点A也与节点C互相q接
可以通过启动节点时指定参?connect_all false来取消默认行?br>
2Q隐藏节点,某些情况下,你希望连接一个节点而不去连接其他节点,你可以通过在节点启动时指定-hidden选项
来启动一个hidden node。在此情况下Q通过nodes()查看所有连接的节点不会出现隐藏的节点Q想看到隐藏的节?br>
可以通过nodes(hidden)或者nodes(connected)来查看?br>
完整的erl选项如下Q?br>
-connect_all false
上面已经解释?
-hidden
启动一个hidden node
-name Name
启动一个系l成点,使用long name.
-setcookie Cookie
?code>Erlang :set_cookie(node(), Cookie).相同Q设|magic cookie
-sname Name
启动一个Erlangpȝ作ؓ节点Q用short name
注意,short name启动的节Ҏ无法与long name节点通信?/span>?br>
.一个小l节Q在Erlang中小于等于是?<表示Q而不是一般语a中的<=语法Q我犯过错误的地方,同样Q不{于都是?P而不?/span>!,比如/=?/=?/span>10.and or 和andalso orelse的区?/span> and和or会计两边的表达式,而andalso和orelse的求值采用短路机Ӟ比如exp1 andalso exp2Q当exp1q回false之后Q就不会L?br>exp2Q而是直接q回falseQ而exp1 and exp2会对exp1和exp2都进行求|or与orelse也类伹{?/pre>
]]> Erlang入门Q三Q——分布式~程 http://www.shnenglu.com/keigoliye/archive/2009/09/11/95886.html暗夜教父 暗夜教父 Fri, 11 Sep 2009 02:13:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/11/95886.html http://www.shnenglu.com/keigoliye/comments/95886.html http://www.shnenglu.com/keigoliye/archive/2009/09/11/95886.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/95886.html http://www.shnenglu.com/keigoliye/services/trackbacks/95886.html 一、分布式机制 下列的BIFs是用于分布式~程Q?br>spawn(Node, Mod, Func, Args) 启动q程节点的一个进E?br>spawn_link(Node, Mod, Func, Args) 启动q程节点的一个进Eƈ创徏q接到该q程monitor_node(Node, Flag) 如果Flag是true,q个函数调用Q该函数Q的q程可以监控节点Node。如果节点已l舍弃或者ƈ不存在,调用的进E将收到一个{nodedown,Node}的消息。如果Flag是false,监控被关闭node() q回我们自己的进Enamenodes() q回其他已知的节点name列表node(Item) q回原来Item的节点名UͼItem可以是Pid,引用QreferenceQ或者端?port)disconnect_node(Nodename) 从节点Nodename断开?br> 节点是分布式Erlang的核心概c在一个分布式Erlang应用中,术语Qterm)节点(nodeQ意味着一个可以加入分布式 transactions的运行系l。通过一个称为net kernal的特D进E,一个独立的Erlangpȝ可以成ؓ一个分布式Erlangpȝ的一部分。当net kernalq程启动的时候,我们U系l是alive的?br> 与远E节点上的进E进行通信Q与同一节点内的q程通信只有一点不同:
java 代码
昄Q需要接收方增加一个参数Node用于指定接受q程所在的节点。节点的name一般是用@隔开的atomcdQ比如pong@dennisQ表C机名ؓdennis上的pong节点。通过执行:
java 代码
在执行的计机中创Z个节点pong。ؓ了运行下面的例子Q你可能需要两台计机Q如果只有一収ͼ只要同时开两个Erlangpȝq以不同的节点名U运行也可以?br> 二、一些例子?br> q个例子完全来自上面提到的翻译的q接Q关于分布式~程的章节。我增加了截囑֒说明?br>首先是代码:
java 代码
-module(tut17).
-export([start_ping/1 , start_pong/ 0 , ping/ 2 , pong/ 0 ]).
ping(0 , Pong_Node) ->
{pong, Pong_Node} ! finished,
io:format("ping finished~n" , []);
ping(N, Pong_Node) ->
{pong, Pong_Node} ! {ping, self()},
receive
pong ->
io:format("Ping received pong~n" , [])
end,
ping(N - 1 , Pong_Node).
pong() ->
receive
finished ->
io:format("Pong finished~n" , []);
{ping, Ping_PID} ->
io:format("Pong received ping~n" , []),
Ping_PID ! pong,
pong()
end.
start_pong() ->
register(pong, spawn(tut17, pong, [])).
start_ping(Pong_Node) ->
spawn(tut17, ping, [3 , Pong_Node]).
代码是创Z个相互通信的进E,怺发送消息ƈ通过io昄在屏q上Q本来是一个单一pȝ的例子,现在我们让两个进E运行在不同的两个节点上。注?start_pingҎQ创建的q程调用pingҎQpingҎ有两个参敎ͼ一个是发送消息的ơ数Q一个就是远E节点的name了,也就是我们将?创徏的进Epong的所在节炏Vstart_pong创徏一个调用函数pong的进E,q注册ؓ名字pongQ因此在pingҎ中可以直接发送消息给 pong)?br> 我是在windows机器上测试,首先打开两个cmdH口Qƈcd到Erlang的安装目录下的bin目录Q比如C:\Program Files\erl5.5.3\bin,上面的E序存ؓtut17.erlQƈ拯到同一个目录下。我们将创徏两个节点Q一个叫 ping@dennis,一个叫pong@dennis,其中dennis是我的机器名。见下图Q?br> 采用同样的命?br> erl - sname ping 创徏ping节点。然后在pong节点下执行start_pong()Q?br> OK,q样在节点pong上启动了pongq程Q然后在ping节点调用start_pingQ传入参数就是pong@dennis
java 代码
tut17:start_ping(pong @dennis ).
执行l果如下图: 同样在pong节点上也可以看到Q?br> l果如我们预期的那样Q不同节点上的两个进E相互通信如此单。我们给模块tut17增加一个方法,用于启动q程q程Q也是调用spawn(Node,Module,Func,Args)ҎQ?br>
java 代码
start(Ping_Node) ->
register(pong, spawn(tut17, pong, [])),
spawn(Ping_Node, tut17, ping, [3 , node()]).
pongq程启动Ping_Node节点上的q程ping。具体结果不再给出?br>
]]> Erlang入门Q四Q——错误处理和鲁棒?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/11/95887.html暗夜教父 暗夜教父 Fri, 11 Sep 2009 02:13:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/11/95887.html http://www.shnenglu.com/keigoliye/comments/95887.html http://www.shnenglu.com/keigoliye/archive/2009/09/11/95887.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/95887.html http://www.shnenglu.com/keigoliye/services/trackbacks/95887.html Erlang的机制有Q?br>1)监控某个表达式的执行 2Q监控其他进E的行ؓ 3Q捕捉未定义函数执行错误{?br>一、catch和throw语句 调用某个会生错误的表达式会D调用q程的非正常退出,比如错误的模式匹配(2=3Q,q种情况下可以用catch语句Q?br> catch expression 试看一个例子,一个函数fooQ?br>
java 代码
foo( 1 ) ->
hello;
foo(2 ) ->
throw ({myerror, abc});
foo(3 ) ->
tuple_to_list(a);
foo(4 ) ->
exit({myExit, 222 }).
当没有用catch的时候,假设有一个标识符为Pid的进E调用函数fooQ在一个模块中Q,那么Q?br>foo(1) - q回hello foo(2) - 语句throw({myerror, abc})执行Q因为我们没有在一个catch中调用foo(2),因此q程Pid因为错误而终止?br> foo(3) - tuple_to_list一个元l{化ؓ列表Q因为a不是元组Q因此进EPid同样因ؓ错误而终?br> foo(4) - 因ؓ没有使用catchQ因此foo(4)调用了exit函数ɘq程Pidl止Q{myExit, 222} 参数用于说明退出的原因?br> foo(5) - q程Pid因为foo(5)的调用而终止,因ؓ没有和foo(5)匚w的函数foo/1?br> 让我们看看用catch之后是什么样Q?br>
java 代码
demo(X) ->
case catch foo(X) of
{myerror, Args} ->
{user_error, Args};
{'EXIT', What} ->
{caught_error, What};
Other ->
Other
end.
再看看结果, demo(1) - 没有错误发生Q因此catch语句返回表辑ּl果hello demo(2) - foo(2)抛出错误{myerror, abc}Q被catchq回Q因此将q回{user_error,abc} demo(3) - foo(3)执行p|Q因为参数错误,因此catchq回{'EXIT',badarg'},最后返回{caught_error,badarg} demo(4) - q回{caught_error,{myexit,222}} demo(5) - q回{caught_error,function_clause} 使用catch和throw可以可能生错误的代码包装hQthrow可以用于N归的退出等{。Erlang是和scheme一栯行尾递归优化的,它们都没有显式的q代l构Q比如for循环Q?br>二、进E的l止 在进E中调用exit的BIFs可以显式地l止q程Qexit(normal)表示正常l止Qexit(Reason)通过Reasonl出非正常终止的原因。进E的l止也完全有可能是因行时错误引v的?br>三、连接的q程 q程之间的连接是双向的,也就是说q程A打开一个连接到B,也意味着有一个从B到A的连接。当q程l止的时候,有一个EXIT信号发l所有与它连接的q程。信L格式如下Q?br> {'EXIT', Exiting_Process_Id, Reason} Exiting_Process_Id 是指l止的进E标记符 Reason 是进E终止的原因。如果Reason是normalQ接受这个信Lq程的默认行为是忽略q个信号。默认对Exit信号的处理可以被重写Q以允许q程对Exit信号的接受做Z同的反应?br>1.q接q程Q?br>通过link(Pid)Q就可以在调用进E与q程Pid之间建立q接 2.取消q接 反之通过unlink(Pid)取消q接? 3.创立q程q连接: 通过spawn_link(Module, Function, ArgumentList)创徏q程q连接,该方法返回新创徏的进EPid 通过q程的相互连接,许多的进E可以组l成一个网状结构,EXIT信号Q非normal)从某个进E发出(该进E终止)Q所有与它相q的q程以及与这些进 E相q的其他q程Q都收到这个信号ƈl止Q除非它们实C自定义的EXIT信号处理Ҏ。一个进E链状结构的例子Q?br>
java 代码
-module(normal).
-export([start/1 , p1/ 1 , test/ 1 ]).
start(N) ->
register(start, spawn_link(normal, p1, [N - 1 ])).
p1(0 ) ->
top1();
p1(N) ->
top(spawn_link(normal, p1, [N - 1 ]),N).
top(Next, N) ->
receive
X ->
Next ! X,
io:format("Process ~w received ~w~n" , [N,X]),
top(Next,N)
end.
top1() ->
receive
stop ->
io:format("Last process now exiting ~n" , []),
exit(finished);
X ->
io:format("Last process received ~w~n" , [X]),
top1()
end.
test(Mess) ->
start ! Mess.
执行Q?br>
java 代码
> normal:start( 3 ).
true
> normal:test(123 ).
Process 2 received 123
Process 1 received 123
Last process received 123
> normal:test(stop).
Process 2 received stop
Process 1 received stop
Last process now exiting
stop
四、运行时p| 一个运行时错误导致进E的非正常终止,伴随着非正常终止EXIT信号发出给所有连接的q程QEXIT信号中有Reasonq且Reason中包含一个atomcd用于说明错误的原因,常见的原因如下:badmatch - 匚wp|Q比如一个进E进?=3的匹配,q个q程终止,q发出{'EXIT', From, badmatch}信号l连接的q程badarg - 思义Q参数错误,比如atom_to_list(123),数字不是atomQ因此将发出{'EXIT', From, badarg}信号l连接进E?br>case_clause - ~少分支匚wQ比?br>
java 代码
M = 3 ,
case M of
1 ->
yes;
2 ->
no
end.
没有分支3Q因此将发出{'EXIT', From, case_clause}l连接进E?br>if_clause - 同理Qif语句~少匚w分支function_clause - ~少匚w的函敎ͼ比如Q?br>
java 代码
foo( 1 ) ->
yes;
foo(2 ) ->
no.
如果我们调用foo(3)Q因为没有匹配的函数Q将发出{'EXIT', From, function_clause} l连接的q程?br>undef - q程执行一个不存在的函?br>badarith - 非法的算术运,比如1+foo?br>timeout_value - 非法的超时时间设|,必须是整数或者infinitynocatch - 使用了throwQ没有相应的catch去通讯?br>五、修攚w认的信号接收action 当进E接收到EXIT信号Q你可以通过process_flag/2Ҏ来修攚w认的接收行ؓ。执行process_flag(trap_exit, true)讄捕获EXIT信号为真来改变默认行为,也就是将EXIT信号作ؓ一般的q程间通信的信可行接受ƈ处理Qprocess_flag (trap_exit,false)重新开启默认行为?br> 例子Q?br>
java 代码
-module(link_demo).
-export([start/0 , demo/ 0 , demonstrate_normal/ 0 , demonstrate_exit/ 1 ,
demonstrate_error/0 , demonstrate_message/ 1 ]).
start() ->
register(demo, spawn(link_demo, demo, [])).
demo() ->
process_flag(trap_exit, true ),
demo1().
demo1() ->
receive
{'EXIT', From, normal} ->
io:format("Demo process received normal exit from ~w~n" ,[From]),
demo1();
{'EXIT', From, Reason} ->
io:format("Demo process received exit signal ~w from ~w~n" ,[Reason, From]),
demo1();
finished_demo ->
io:format("Demo finished ~n" , []);
Other ->
io:format("Demo process message ~w~n" , [Other]),
demo1()
end.
demonstrate_normal() ->
link(whereis(demo)).
demonstrate_exit(What) ->
link(whereis(demo)),
exit(What).
demonstrate_message(What) ->
demo ! What.
demonstrate_error() ->
link(whereis(demo)),
1 = 2 .
创徏的进E执行demoҎQdemoҎ中设|了trap_exit为true,因此Q在receive中可以像对待一般的信息一样处理EXIT信号Q这个程序是很简单了Q测试看看:
java 代码
> link_demo:start().
true
> link_demo:demonstrate_normal().
true
Demo process received normal exit from <0.13 . 1 >
> link_demo:demonstrate_exit(hello).
Demo process received exit signal hello from <0.14 . 1 >
** exited: hello **
> link_demo:demonstrate_exit(normal).
Demo process received normal exit from <0.13 . 1 >
** exited: normal **
> link_demo:demonstrate_error().
!!! Error in process <0.17 . 1 > in function
!!! link_demo:demonstrate_error()
!!! reason badmatch
** exited: badmatch **
Demo process received exit signal badmatch from <0.17 . 1 >
六、未定义函数和未注册名字 1.当调用一个未定义的函数时QMod:Func(Arg0,...,ArgN)Q这个调用将被{为: error_handler:undefined_function(Mod, Func, [Arg0,...,ArgN]) 其中的error_handler模块是系l自带的错误处理模块 2.当给一个未注册的进E名发送消息时Q调用将被{为: error_handler:unregistered_name(Name,Pid,Message) 3.如果不用系l自带的error_handlerQ可以通过process_flag(error_handler, MyMod) 讄自己的错误处理模块?br>七、Catch Vs. Trapping Exits q两者的区别在于应用场景不同QTrapping Exits应用于当接收到其他进E发送的EXIT信号Ӟ而catch仅用于表辑ּ的执行?br> W?章介l了如何利用错误处理机制L造一个健壮的pȝQ用了几个例子,我将8.2节的例子完整写了下,q添加客Lq程用于试Q?br>
java 代码
-module(allocator).
-export([start/1 ,server/ 2 ,allocate/ 0 ,free/ 1 ,start_client/ 0 ,loop/ 0 ]).
start(Resources) ->
Pid = spawn(allocator, server, [Resources,[]]),
register(resource_alloc, Pid).
%函数接口
allocate() ->
request(alloc).
free(Resource) ->
request({free,Resource}).
request(Request) ->
resource_alloc ! {self(),Request},
receive
{resource_alloc, error} ->
exit(bad_allocation); % exit added here
{resource_alloc, Reply} ->
Reply
end.
% The server.
server(Free, Allocated) ->
process_flag(trap_exit, true ),
receive
{From,alloc} ->
allocate(Free, Allocated, From);
{From,{free,R}} ->
free(Free, Allocated, From, R);
{'EXIT', From, _ } ->
check(Free, Allocated, From)
end.
allocate([R|Free], Allocated, From) ->
link(From),
io:format("q接客户端进E~w~n" ,[From]),
From ! {resource_alloc,{yes,R}},
server(Free, [{R,From}|Allocated]);
allocate([], Allocated, From) ->
From ! {resource_alloc,no},
server([], Allocated).
free(Free, Allocated, From, R) ->
case lists:member({R,From}, Allocated) of
true ->
From ! {resource_alloc,ok},
Allocated1 = lists:delete({R, From}, Allocated),
case lists:keysearch(From, 2 ,Allocated1) of
false ->
unlink(From),
io:format("从进E~w断开~n" ,[From]);
_->
true
end,
server([R|Free],Allocated1);
false ->
From ! {resource_alloc,error},
server(Free, Allocated)
end.
check(Free, Allocated, From) ->
case lists:keysearch(From, 2 , Allocated) of
false ->
server(Free, Allocated);
{value, {R, From}} ->
check([R|Free],
lists:delete({R, From}, Allocated), From)
end.
start_client()->
Pid2=spawn(allocator,loop,[]),
register(client, Pid2).
loop()->
receive
allocate->
allocate(),
loop();
{free,Resource}->
free(Resource),
loop();
stop->
true ;
_->
loop()
end.
回家了,有空再详l说明下q个例子吧。执行:
java 代码
1 > c(allocator).
{ok,allocator}
2 > allocator:start([ 1 , 2 , 3 , 4 , 5 , 6 ]).
true
3 > allocator:start_client().
true
4 > client!allocate
.
allocateq接客户端进E?lt;0.37 . 0 >
5 > client!allocate.
allocateq接客户端进E?lt;0.37 . 0 >
6 > client!allocate.
allocateq接客户端进E?lt;0.37 . 0 >
7 > allocator:allocate().
q接客户端进E?lt;0.28 . 0 >
{yes,4 }
8 > client!{free, 1 }.
{free,1 }
9 > client!{free, 2 }.
{free,2 }
10 > client!allocate.
allocateq接客户端进E?lt;0.37 . 0 >
11 > client!allocate.
allocateq接客户端进E?lt;0.37 . 0 >
12 > client!stop.
stop
13 > allocator:allocate().
q接客户端进E?lt;0.28 . 0 >
{yes,3 }
14 > allocator:allocate().
q接客户端进E?lt;0.28 . 0 >
{yes,2 }
15 > allocator:allocate().
q接客户端进E?lt;0.28 . 0 >
{yes,1 }
16 >
]]> Erlang入门Q二Q—ƈ发编E?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/11/95885.html暗夜教父 暗夜教父 Fri, 11 Sep 2009 02:12:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/11/95885.html http://www.shnenglu.com/keigoliye/comments/95885.html http://www.shnenglu.com/keigoliye/archive/2009/09/11/95885.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/95885.html http://www.shnenglu.com/keigoliye/services/trackbacks/95885.html Erlang中的process——进E是轻量U的Qƈ且进E间无共享。查了很多资料,g没h说清楚轻量q程是什么概念,l箋查找中。。。闲话不 提,q入q发~程的世界。本文算是学习笔讎ͼ也可以说是《Concurrent Programming in ERLANG》第五张的简略翻译?1.q程的创?/span> q程是一U自包含的、分隔的计算单元Qƈ与其他进Eƈ发运行在pȝ中,在进E间q没有一个承体p,当然Q应用开发者可以设计这样一个承体pR?br> q程的创Z用如下语法:
java 代码
Pid = spawn(Module, FunctionName, ArgumentList)
spawn接受三个参数Q模块名Q函数名以及参数列表Qƈq回一个代表创建的q程的标识符QPidQ?br>如果在一个已知进EPid1中执行:
java 代码
Pid2 = spawn(Mod, Func, Args)
那么QPid2仅仅能被Pid1可见QErlangpȝ的安全性就构徏在限制进E扩展的基础上?br>2.q程间通信 Erlangq程间的通信只能通过发送消息来实现Q消息的发送?W号Q?br>
java 代码
其中Pid是接受消息的q程标记W,Message是消息。接受方和消息可以是M的有效的Erlangl构Q只要他们的l果q回的是q程标记W和消息?br> 消息的接受是使用receive关键字,语法如下Q?br>
java 代码
receive
Message1 [when Guard1] ->
Actions1 ;
Message2 [when Guard2] ->
Actions2 ;
end
每一个Erlangq程都有一?#8220;邮箱”Q所有发送到q程的消息都按照到达的顺序存储在“邮箱”里,上面所C的消息Message1,Message2Q?当它们与“邮箱”里的消息匚wQƈ且约束(GuardQ通过Q那么相应的ActionN执行,q且receiveq回的是ActionN的最后一条执?语句的结果。Erlang?#8220;邮箱”里的消息匚w是有选择性的Q只有匹配的消息被触发相应的ActionQ而没有匹配的消息仍然保留在“邮箱”里。这 一机制保证了没有消息会d其他消息的到达?br> 消息到达的顺序ƈ不决定消息的优先U,q程轮检?#8220;邮箱”里的消息q行试匚w。消息的优先U别下文再讲?br> 如何接受特定q程的消息呢Q答案很单,发送方(sender)也附送在消息当中Q接收方通过模式匚w军_是否接受Q比如:
java 代码
l进EPid发送消息{self(),abc}Q利用selfq程得到发送方作ؓ消息发送。然后接收方Q?br>
java 代码
receive
{Pid1,Msg} ->
end
通过模式匚w军_只有Pid1q程发送的消息才接受?br>3.一些例?/span> 仅说明下书中计数的进E例?我添加了单注释:
java 代码
-module(counter).
-compile(export_all).
% start()Q返回一个新q程Q进E执行函数loop
start()->spawn(counter, loop,[0 ]).
% 调用此操作递增计数
increment(Counter)->
Counter!increament.
% q回当前计数?nbsp;
value(Counter)->
Counter!{self(),value},
receive
{Counter,Value}->
%q回l调用方
Value
end.
%停止计数
stop(Counter)->
Counter!{self(),stop}.
loop(Val)->
receive
%接受不同的消息,军_q回l果
increament->
loop(Val+1 );
{From,value}->
From!{self(),Val},
loop(Val);
stop->
true ;
%不是以上3 U消息,ql等?nbsp;
Other->
loop(Val)
end.
调用方式Q?br>
java 代码
1 > Counter1=counter:start().
<0.30 . 0 >
2 > counter:value(Counter1).
0
3 > counter:increment(Counter1).
increament
4 > counter:value(Counter1).
1
Zq程的消息传递机制可以很Ҏ地实现有限状态机QFSMQ,状态用函数表C,而事件就是消息。具体不再展开4.时讄 Erlang中的receive语法可以d一个额外选项QtimeoutQ类|
java 代码
receive
Message1 [when Guard1] ->
Actions1 ;
Message2 [when Guard2] ->
Actions2 ;
after
TimeOutExpr ->
ActionsT
end
after之后的TimeOutExpr表达式返回一个整数timeQ毫U别)Q时间的_E度依赖于Erlang在操作系l或者硬件的实现。如果在time毫秒内,没有一个消息被选中Q超时设|将生效Q也是ActionT执行。time有两个特D| 1)infinity (无穷?Qinfinity是一个atomQ指定了时讄永q不会被执行?br>2) 0 Q超时如果设定ؓ0意味着时讄立L行,但是pȝ首先尝试当?#8220;邮箱”里的消息?br> 时的常见几个应用,比如挂v当前q程多少毫秒Q?br>
java 代码
sleep(Time) ->
receive
after Time ->
true
end.
比如清空q程?#8220;邮箱”,丢弃“邮箱”里的所有消息:
java 代码
flush_buffer() ->
receive
AnyMessage ->
flush_buffer()
after 0 ->
true
end.
当前进E永q挂P
java 代码
suspend() ->
receive
after
infinity ->
true
end.
时也可以应用于实现定时器,比如下面q个例子Q创Z个进E,q个q程在讑֮旉后向自己发送消息:
java 代码
-module(timer).
-export([timeout/2 ,cancel/ 1 ,timer/ 3 ]).
timeout(Time, Alarm) ->
spawn(timer, timer, [self(),Time,Alarm]).
cancel(Timer) ->
Timer ! {self(),cancel}.
timer(Pid, Time, Alarm) ->
receive
{Pid,cancel} ->
true
after Time ->
Pid ! Alarm
end.
5、注册进E?/span> Zl进E发送消息,我们需要知道进E的PidQ但是在某些情况下:在一个很大系l里面有很多的全局serversQ或者ؓ了安全考虑需要隐藏进E?Pid。ؓ了达到可以发送消息给一个不知道Pid的进E的目的Q我们提供了注册q程的办法,l进E们注册名字Q这些名字必Latom?br> 基本的调用Ş式:
java 代码
register(Name, Pid)
Name与进EPid联系h
unregister(Name)
取消Name与相应进E的对应关系?nbsp;
whereis(Name)
q回Name所兌的进E的PidQ如果没有进E与之关联,p回atom:undefined
registered()
q回当前注册的进E的名字列表
6.q程的优先 讑֮q程的优先可以使用BIFs:process_flag(priority, Pri) Pri可以是normal、low,默认都是normal 优先U高的进E将相对低的执行多一炏V?br>7.q程l(process group) 所有的ERLANGq程都有一个Pid与一个他们共有的UCؓGroup Leader相关联,当一个新的进E被创徏的时候将被加入同一个进E组。最初的pȝq程的Group Leader是它自w,因此它也是所有被创徏q程及子q程的Group Leader。这意味着Erlang的进E被l织ZTreeQ其中的根节点就是第一个被创徏的进E。下面的BIFs被用于操U进E组Q?br>group_leader() q回执行q程的Group Leader的Pidgroup_leader(Leader, Pid) 讄q程Pid的Group LeaderE的Leader 8. Erlang的进E模型很ҎL建Client-Server的模型,书中有一节专门讨Zq一点,着重强调了接口的设计以及抽象层ơ的隔离问题Q不译了?/span>
]]> Erlang入门Q一Q?/title> http://www.shnenglu.com/keigoliye/archive/2009/09/11/95884.html暗夜教父 暗夜教父 Fri, 11 Sep 2009 02:11:00 GMT http://www.shnenglu.com/keigoliye/archive/2009/09/11/95884.html http://www.shnenglu.com/keigoliye/comments/95884.html http://www.shnenglu.com/keigoliye/archive/2009/09/11/95884.html#Feedback 0 http://www.shnenglu.com/keigoliye/comments/commentRss/95884.html http://www.shnenglu.com/keigoliye/services/trackbacks/95884.html 读erlang.org上面的Erlang Course四天教程1. 数字cdQ需要注意两?br>1QB#Val表示以Bq制存储的数字ValQ比?br>
ruby 代码
?/span>q制存储?01是10q制??br>2Q?Char表示字符Char的ascii~码Q比?A表示652. 比较难以译的概念——atomQ可以理解成帔RQ它可以包含M字符Q以写字母开_如果不是以小写字母开头或者是字母之外的符P需要用单引号包括v来,比如abc,'AB'3. 另一个概念——Tuple,有h译成元l,可以理解成定长数l,是Erlang的基数据l构之一Q?br>
ruby 代码
8> {1,2,3,4,5}.
{1,2,3,4,5}
9> {a,b,c,1,2}.
{a,b,c,1,2}
10> size({1,2,3,a,b,c}).
6
内置函数size求长度,元组可以嵌套元组或者其他结构。下面所讲的列表也一栗?br>4. 另外一个基数据l构是各个语言都有的listQ列表)Q在[]内以,隔开Q可以动态改变大,
python 代码
[123, xyz]
[123, def , abc]
[{person, 'Joe', 'Armstrong'},
{person, 'Robert', 'Virding'},
{person, 'Mike', 'Williams'}
]
可以使用内置函数length求列表大。以""包含的ascii字母代表一个列表,里面的元素就是这些字母的ascii|比如"abc"表示列表[97,98,99]?br>5. 通过q两个数据结构可以组合成各种复杂l构Q与Lisp的cons、list演化出各U结构一L奇妙?br>6. Erlang中变量有两个特点Q?br>1Q变量必M大写字母开?br>2Q变量只能绑定一ơ,或者以一般的说法是只能赋gơ,其实Erlangq没有赋DL概念,=号也是用于验证匹配?br>7. 模式匚w——Pattern MatchingQErlang的模式匹配非常强大,看了buaawhl 的?a >Erlang语法提要 》的介绍Q模式匹配的功能不仅仅在评中介l的数据l构的拆解,在程序的分派也扮演重要角Ԍ或者说Erlang的控制的{是通过模式匚w来实现的。具体功能参见链接,l出书中拆解列表的例子:
python 代码
[A,B|C] = [1,2,3,4,5,6,7]
Succeeds - binds A = 1, B = 2,
C = [3,4,5,6,7]
[H|T] = [1,2,3,4]
Succeeds - binds H = 1, T = [2,3,4]
[H|T] = [abc]
Succeeds - binds H = abc, T = []
[H|T] = []
Fails
下面会给出更多模式匹配的例子Q给Z个模块用来计列表等8. Erlang中函数的定义必须在一个模块内QModuleQ,q且模块和函数的名称都必LatomQ函数的参数可以是Q何的Erlangcd或者数据结构,函数要被调用需要从模块中导出,函数调用的Ş式类| moduleName:funcName(Arg1,Arg2,...). 写我们的W一个ErlangE序Qh见hqHello WorldQ?br>
java 代码
-module(helloWorld).
-export([run/1 ]).
run(Name)->
io:format("Hello World ~w~n" ,[Name]).
存ؓhelloWorld.erlQ在Erlang Shell中执行:
java 代码
2 > c(helloWorld).
{ok,helloWorld}
3 > helloWorld:run(dennis).
Hello World dennis
ok
打印出来了,现在解释下程序构造,
java 代码
q一行声明了模块helloWorldQ函数必d义在模块内,q且模块名称必须与源文g名相同?br>
java 代码
而这一行声明导出的函数Qrun/1指的是有一个参数的run函数Q因为Erlang允许定义同名的有不同参数的多个函敎ͼ通过指定/1来说明要导出的是哪个函数?br>接下来就是函数定义了Q?br>
java 代码
run(Name)->
io:format("Hello World ~w~n" ,[Name]).
大写开头的是变量NameQ调用io模块的formatҎ输出Q~w可以理解成占位符Q将被实际Name取代Q~n是换行了。注意,函数定义完了要以句号.l束。然后执行c(helloWorld).~译源代码,执行Q?br>
java 代码
9. 内置的常用函敎ͼ
java 代码
date()
time()
length([1 , 2 , 3 , 4 , 5 ])
size({a,b,c})
atom_to_list(an_atom)
list_to_tuple([1 , 2 , 3 , 4 ])
integer_to_list(2234 )
tuple_to_list({})
hd([1 , 2 , 3 , 4 ]) %输出 1 Q也是列表的head
tl([1 , 2 , 3 , 4 ]) %输出[ 2 , 3 , 4 ],也就是列表的tail
10. 常见Shell命oQ?br>1Q?span style="FONT-WEIGHT: bold">h(). 用来打印最q的20条历史命?br>2Q?span style="FONT-WEIGHT: bold">b(). 查看所有绑定的变量 3) f(). 取消Q遗忘)所有绑定的变量?br>4) f(Val). 取消指定的绑定变?br>5) e(n). 执行Wn条历史命?br>6) e(-1). 执行上一条shell命o11. 又一个不知道怎么译的概念——Guard。翻译成U束Q呵c用于限制变量的cd和范_比如Q?br>
java 代码
number(X) - X 是数?nbsp;
integer(X) - X 是整?nbsp;
float (X) - X 是QҎ
atom(X) - X 是一个atom
tuple(X) - X 是一个元l?nbsp;
list(X) - X 是一个列?nbsp;
length(X) == 3 - X 是一个长度ؓ 3 的列?nbsp;
size(X) == 2 - X 是一个长度ؓ 2 的元l?nbsp;
X > Y + Z - X >Y+Z
X == Y - X 与Y相等
X =:= Y - X 全等于Y
(比如Q?nbsp;1 == 1.0 成功
1 =:= 1.0 p|)
Z方便比较QErlang规定如下的比较顺序:
java 代码
number < atom < reference < port < pid < tuple < list
12. 忘了介绍apply函数Q这个函数对于熟悉javascript的h来说很亲切,javascript实现mixin得靠它Q它的调用方式如下:
apply(Mod, Func, Args),三个参数分别是模块、函C及参数列表,比如调用我们的第一个ErlangE序Q?br>
java 代码
apply(helloWorld,run,[dennis]).
13. if和case语句Qif语句的结构如下:
java 代码
if
Guard1 ->
Sequence1 ;
Guard2 ->
Sequence2 ;
...
end
而case语句的结构如下:
java 代码
case Expr of
Pattern1 [when Guard1] -> Seq1;
Pattern2 [when Guard2] -> Seq2;
PatternN [when GuardN] -> SeqN
end
if和case语句都有一个问题,是当没有模式匹配或者Grard都是false的时候会DerrorQ这个问题case可以增加一个类似java中default的:
java 代码
通过_指代L的ExprQ返回true,而if可以q样Q?br>
java 代码
一L道理。case语句另一个需要注意的问题是变量范围Q每个case分支中定义的变量都将默认导出case语句Q也是在case语句l束后可以被引用Q因此一个规则就是每个case分支定义的变量应该一_不然是非法的,~译器会l出警告Q比如:
java 代码
f(X) ->
case g(X) of
true -> A = h(X), B = A + 7 ;
false -> B = 6
end,
h(A).
如果执行true分支Q变量A和变量B都被定义Q而如果执行的false分支Q只有变量B被引用,可在case语句执行后,h(A)调用了变量AQ这是不安全的,因ؓ变量A完全可能没有被定义,~译器将l出警告variable 'A' unsafe in 'case' (line 10) 14. l出一些稍微复杂的模型匚w例子Q比如用于计数字列表的和、^均倹{长度、查找某元素是否在列表中Q我们把q个模块定义为list:
java 代码
-module(list).
-export([average/1 ,sum/ 1 ,len/ 1 , double / 1 ,member/ 2 ]).
average(X)->sum(X)/len(X).
sum([H|T]) when number(H)->H+sum(T);
sum([])->0 .
len([_|T])->1 +len(T);
len([])->0 .
double ([H|T]) -> [ 2 *H| double (T)];
double ([]) -> [].
member(H, [H|_]) -> true ;
member(H, [_|T]) -> member(H, T);
member(_, []) -> false .
l细体会Q利用递归来实玎ͼ比较有趣。_用于指代L的变量,当我们只x此处有变量,但ƈ不关心变量的值的时候用。用分号;来说明是同一个函数定义,只是不同的定义分支,通过模式匚w来决定调用哪个函数定义分支?br>另一个例子,计算各种囑Ş的面U,也是评中给出的例子Q?br>
java 代码
-module(mathStuff).
-export([factorial/1 ,area/ 1 ]).
factorial(0 )-> 1 ;
factorial(N) when N>0 ->N*factorial(N- 1 ).
%计算正方形面U,参数元组的第一个匹配square
area({square, Side}) ->
Side * Side;
%计算圆的面积Q匹配circle
area({circle, Radius}) ->
% almost :-)
3 * Radius * Radius;
%计算三角形的面积Q利用v伦公式,匚wtriangle
area({triangle, A, B, C}) ->
S = (A + B + C)/2 ,
math:sqrt(S*(S-A)*(S-B)*(S-C));
%其他
area(Other) ->
{invalid_object, Other}.
执行一下看看:
java 代码
1 > c(mathStuff).
{ok,mathStuff}
2 > mathStuff:area({square, 2 }).
4
3 > mathStuff:area({circle, 2 }).
12
4 > mathStuff:area({triangle, 2 , 3 , 4 }).
2.90474
5 > mathStuff:area({other, 2 , 3 , 4 }).
{invalid_object,{other,2 , 3 , 4 }}
Erlang使用%开始单行注释?br>
]]>
ŷպƷþþþ |
þҹɫƷAV |
þŷƷ |
vĻþ |
ھƷ˾þþþavһ |
ݺɫۺþö
|
˾Ʒþۺ |
þۺ |
뾫Ʒþþþ.. |
˾þۺ3d |
ۿƷþ |
þþƷĻ̾ |
ɫþþþþۺ |
þ96Ʒþþ |
ݺɫ˾þþƷۺ
|
Ʒþþþþۺձ |
鶹Ʒþþһ |
ƷžžþƵ
|
Ʒרþþ |
ɫþþ99Ʒ |
wwwþ |
þۺϺݺۺϾþ |
ĻƷþ |
˾Ʒþ |
Ʒþþþ9999 |
þþƷAVɫ |
þwww˳ɿƬ |
þ99ȾƷ |
պĻþ |
ƷþëƬ |
þþþùƷ۲ӰԺ |
ѾþþƷѾѾ |
þѹƷһ |
ƷþþþþþþѼ |
þAVӰ |
ҹþþþüŮӰԺ |
AŮAVۺϾþþ |
þۺϾɫۺϾ99 |
þøһëƬ |
ϵרþ |
þþƷ72 |