erlang efficient guide 3

[color=darkred][b]* 3 Common Caveats
* 3常见的注意事项[/b][/color]

Here we list a few modules and BIFs to watch out for, and not only from a performance point of view.
下面我们来看-看erlang的一些常用module和bif,不仅仅从性能的角度去考虑。

[b]3.1 The timer module
3.1 timer模块[/b]

[list]
[*]Creating timers using erlang:send_after/3 and erlang:start_timer/3 is much more efficient than using the timers provided by the timer module. The timer module uses a separate process to manage the timers, and that process can easily become overloaded if many processes create and cancel timers frequently (especially when using the SMP emulator).
[/list]
[list]
[*]使用erlang:send_after/3 和erlang:start_timer/3会比使用time模块内的函数高效得多。timer 模块使用一个独立的进程来管理时间,这个进程如果大量的进程频繁去创建和取消时间很容易就超负荷了(特别是使用SMP方式的时候)
[/list]

[list]
[*]The functions in the timer module that do not manage timers (such as timer:tc/3 or timer:sleep/1), do not call the timer-server process and are therefore harmless.
[/list]
[list]
[*]有一些timer内不管理时间定时器的函数(例如:timer:tc/3, timer:sleep/1),不去调用定时器server进程的函数都是无害的。【也就是说:有些timer里面的函数是不依赖于这个server的,可以随意用】
[*]【附】关于erlang:send_after/3与erlang:send_time/3的区别【cancle_timer/1只能去掉那些没有超时的信息,没发出去的】
[*]http://www.cnblogs.com/me-sa/archive/2012/03/16/erlang-timer.html
[*]这时候send_after里面存放的是Msg, 那用户如何知道Msg是对于那个TimerRef的呢? 读者可能说, 那我可以在消息里面加入TimerRef. 这个主意不错, 但是问题是在send_after调用返回之前, 你是无法得到TimerRef, 当然也就无从构造这个消息, 那就无法处理这个可能的超时信息, 就会破坏逻辑.
[*]所以erts version 5.4.11 引入了, start_timer来解决这个问题. 它是自动的在超时后, 要发送消息前, 在消息里面添加了{timeout, TimerRef, Msg}, 达到识别的目的
[/list]

[list]
[*]erlang使用timer有3中方式:
[*]1. 语法层面的 receive ... after ...
[*] 这个是opcode实现的,一旦timeout立即把process加到调度队列,使用频度比较高。
[*]2. bif
[*] erlang:send_after(Time, Dest, Msg) -> TimerRef
[*] erlang:start_timer(Time, Dest, Msg) -> TimerRef
[*] 这个一旦timeout就给Dest发送一条消息,使用频度不是很高。
[*]3.driver层面的。
[*] int driver_set_timer(ErlDrvPort port, unsigned long time);
[*] inet_driver大量使用这个api. tcp/udp进程需要超时处理,所以有大量的连接的时候这种timer的数量非常大。定时器超时后把port_task加到调度队列。
[*]定时器的最早超时时间用于poll的等待时间。
[*]整个定时器由bump_timer来驱动。bump_timer是在schedule的时候不定期调用的。总之使用timer的时候要小心,因为timer实在scheduler的线程里面调用的,不能做非常耗时的操作,否则会阻塞调度器。
[*]
[*]【因为项目中有大量的秒循环,,如果可以使用一个总的send_after/3来给驱动各个子的秒循环(用一个管理秒循环的每秒给各服务发一个信息,来做比较自己服务器起一个erlang:send_after/3),就不用频繁的调用erlang:send_after/3了,听项目负责人是这样说的。但是没去看。。。。。】
[*]Ps 最后一篇的erl -s module func arg1 arg2 很吊哦。
[/list]
3.2 list_to_atom/1
[b]3.2 list_to_atom/1[/b]
[list]
[*]Atoms are not garbage-collected. Once an atom is created, it will never be removed. The emulator will terminate if the limit for the number of atoms (1048576 by default) is reached
.[/list]
[list]
[*]原子是不会被垃圾回收器回收的,原子一旦创建,不会被移除,如果原子的数量达到最大值(默认为1048576 )emulator(模拟器?)就会挂掉。
[/list]
[list]
[*]Therefore, converting arbitrary input strings to atoms could be dangerous in a system that will run continuously. If only certain well-defined atoms are allowed as input, you can use list_to_existing_atom/1 to guard against a denial-of-service attack. (All atoms that are allowed must have been created earlier, for instance by simply using all of them in a module and loading that module.)
[/list]
[list]
[*]所以,将任意字符串转化为原子在一个持续动作的系统时是非常危险的。如果只有定义好的原子能够作为输入,你可以使用list_to_exiting_atom/1来作为一种避免出现危机的手段。(所以的允许的原子必须创建早些,比如:通过简单的定义所有的原子在同一模块并加载此模块来实现。)
[/list]
[list]
[*]Using list_to_atom/1 to construct an atom that is passed to apply/3 like this
[*]apply(list_to_atom("some_prefix"++Var), foo, Args)
[/list]
[list]
[*]以上是错的行为:
[*]is quite expensive and is not recommended in time-critical code.
[*]在apply/3的参数中使用list_to_atom/1把string(也是一种list)转化为原子来调用。是非常耗性能的,非常不推荐啊
[/list]
[b]3.3 length/1
3.3 length/1求列表长[/b]
[list]
[*]The time for calculating the length of a list is proportional to the length of the list, as opposed to tuple_size/1, byte_size/1, and bit_size/1, which all execute in constant time.
[/list]
[list]
[*]执行length/1的时间取决于列表的长度,矶tuple_size/1,byte_size/1, and bit_size/1则是一个固定的值
[/list]
[list]
[*]Normally you don't have to worry about the speed of length/1, because it is efficiently implemented in C. In time critical-code, though, you might want to avoid it if the input list could potentially be very long.
[/list]
[list]
[*]正常情况下,你不用担心length/1的执行速度,因为他是用c写的高效代码,在关键性的代码时,一定要禁止在列表很长的时候调用length/1。
[/list]
[list]
[*]Some uses of length/1 can be replaced by matching. For instance, this code
[/list]
[list]
[*]一些用length/1的地方可以用模式匹配来做,例如:
[/list]
foo(L) when length(L) >= 3 ->
...

can be rewritten to

foo([_,_,_|_]=L) ->
...

[list]
[*](One slight difference is that length(L) will fail if the L is an improper list, while the pattern in the second code fragment will accept an improper list.)
[/list]
[list]
[*](一点不同之处在于:length(L)会在L不是一个正当的列表时失败,而第二种情况则能适应不正当的列表。)
[/list]

[b]3.4 setelement/3
3.4 setelement/3 setelement(Index, Tuple1, Value) -> Tuple2[/b]

[list]
[*]setelement/3 copies the tuple it modifies. Therefore, updating a tuple in a loop using setelement/3 will create a new copy of the tuple every time.
[/list]
[list]
[*]setelement/3 会复制那个要修改的元组,在每一次更新用setelement/3都会创建一个新的元组哦。
[/list]

[list]
[*]There is one exception to the rule that the tuple is copied. If the compiler clearly can see that destructively updating the tuple would give exactly the same result as if the tuple was copied, the call to setelement/3 will be replaced with a special destructive setelement instruction. In the following code sequence
[/list]
[list]
[*]不会复制的唯一例外:当编译器清楚知道更新后的元组和原来一样时,那么使用setelement/3会被一种特殊的setelement 结构所替代,请看下面的代码
[/list]
multiple_setelement(T0) ->
T1 = setelement(9, T0, bar),
T2 = setelement(7, T1, foobar),
setelement(5, T2, new_value).

[list]
[*]the first setelement/3 call will copy the tuple and modify the ninth element. The two following setelement/3 calls will modify the tuple in place.
[/list][list]
[*]第一个setelement/3函数会复制元组并修改第九个元素。后面两个setelement/3函数会直接修改这个元组。
[/list]
[list]
[*]For the optimization to be applied, all of the followings conditions must be true:
[/list]
[list]
[*]要让上面的优化起作用,下面的原则是要必须遵守的:
[/list]

[list]
[*]* The indices must be integer literals, not variables or expressions.
[*] * The indices must be given in descending order.
[*] * There must be no calls to other function in between the calls to setelement/3.
[*] * The tuple returned from one setelement/3 call must only be used in the subsequent call to setelement/3.
[/list] [list]
[*]* 索引必须是一个合法的数字,不是变量,或表达式
[*] * 索引必须是降序的
[*] * 在使用setelement/3的中间不要调用其它任务函数
[*] * 一个setelement/3后面的结果必然是下一个setelement/3的输入
[/list]
[list]
[*]If it is not possible to structure the code as in the multiple_setelement/1 example, the best way to modify multiple elements in a large tuple is to convert the tuple to a list, modify the list, and convert the list back to a tuple.
[/list]
[list]
[*]multiple_setelement/1 的例子并不多见,修改元组中的多个元素通常的情况是:把一个大的元组转化为一个列表,然后修改列表,再转化为元组。
[/list]
[b]3.5 size/1
3.5 size/1[/b]
[list]
[*]size/1 returns the size for both tuples and binary.
[*]size/1求元组和二进制的大小
[/list]
[list]
[*]Using the new BIFs tuple_size/1 and byte_size/1 introduced in R12B gives the compiler and run-time system more opportunities for optimization. A further advantage is that the new BIFs could help Dialyzer find more bugs in your program.
[/list]
[list]
[*]使用R12B更新的BIFs tuple_size/1 和byte_size/1 会让运行时系统更加高效,使用新的bifs的一个长久的优点在于Dialyzer 可以帮助程序发现更多隐藏的bug.
[/list]
[b]3.6 split_binary/2
3.6 split_binary/2 [/b]
[list]
[*]It is usually more efficient to split a binary using matching instead of calling the split_binary/2 function. Furthermore, mixing bit syntax matching and split_binary/2 may prevent some optimizations of bit syntax matching.
[/list]
[list]
[*]使用比特语法来分离二进制比用split_binary/2更加高效,更进一步来讲,混合使用比特语法和split_binary/2会把编译器弄sb的(不会进行相关的优化任务了)
[/list]
DO

 <<Bin1:Num/binary,Bin2/binary>> = Bin,

DO NOT

 {Bin1,Bin2} = split_binary(Bin, Num)

[b]3.7 The '--' operator
3.7 “--”操作符[/b]
[list]
[*]Note that the '--' operator has a complexity proportional to the product of the length of its operands, meaning that it will be very slow if both of its operands are long lists:
[/list]
[list]
[*]Note: "--"操作符非常依赖于列表的长度,长度越长越慢!
[/list]DO NOT

 HugeList1 -- HugeList2

Instead use the ordsets module:

DO

HugeSet1 = ordsets:from_list(HugeList1),
HugeSet2 = ordsets:from_list(HugeList2),
ordsets:subtract(HugeSet1, HugeSet2)


[list]
[*]Obviously, that code will not work if the original order of the list is important. If the order of the list must be preserved, do like this:
[/list]
[list]
[*]显然,上面的代码不能保证原来列表的顺序,如果要保留,则用下面的代码:
[/list]DO


Set = gb_sets:from_list(HugeList2),
[E || E <- HugeList1, not gb_sets:is_element(E, Set)]


[list]
[*]Subtle note 1: This code behaves differently from '--' if the lists contain duplicate elements. (One occurrence of an element in HugeList2 will remove all occurrences in HugeList1.)
[/list]
[list]
[*]注意事项1:这与--不同的在于:如果原列表中有重复的元素都会被移除
[/list]
[list]
[*]Subtle note 2: This code compares lists elements using the '==' operator, while '--' uses the '=:='. If that difference is important, sets can be used instead of gb_sets, but note that sets:from_list/1 is much slower than gb_sets:from_list/1 for long lists.
[/list]
[list]
[*]注意事项2:这使用'=='来比较列表元素,而'--'操作符使用'=:='来比较列表元素。如果这个区别显得很重要,那么可以用sets模块来替代gb_sets模块,但是记住,对于长列表,sets:from_list/1函数比gb_sets:from_list/1函数要慢得多。
[/list]
[list]
[*]Using the '--' operator to delete an element from a list is not a performance problem:
[/list]
[list]
[*]使用 --来删除列表中的一个元素是没的性能问题的。
[/list]
OK

 HugeList1 -- [Element]

Copyright © 2001-2013 Ericsson AB. All Rights Reserved.

[img]http://dl2.iteye.com/upload/attachment/0088/3851/1b444e4b-0af4-3be5-ace6-74d54a9bce62.jpg[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值