zoukankan      html  css  js  c++  java
  • erlang的“缺点”

    erlang的优点

    1、并发简单

    2、热更新

    3、易于学习

    为什么要学erlang?

    erlang底层实现是C

    所有简单来说,如果一个很精通C的程序员(20年+)肯定是比一个常规的erlang程序员写出的代码效率更高。

    其实这个对于底层基于C的大部分语言(JAVA等)都是一个道理,

    可是为什么要学erlang呢,因为成本,一个精通C的程序员培养的成本太大(这也是为什么JAVA程序员很多^_^)

    什么时候用erlang解决问题?

    erlang擅长的是大计算,小消息

    简单的说,如果一个逻辑比较复杂的功能,而且结果是成本较低(相比逻辑实现来说),就可以用erlang

    如果逻辑比较简单或者结果和逻辑差不多,就不适合了

    下面我们举个例子来证明这种“缺点”

    比如现在我要求一个整数里面所有的质数(只能被1和自己整除的数,假设1和2都是不是质数)

    首先我们用C实现,为了方便比较我们用erlang nif调用C(理论只用C更快)

    代码如下

    #include <stdbool.h>  
    #include <math.h>  
    #include "erl_nif.h"  
      
    static bool isPrime(int i)  
    {  
            int j;  
            int t = sqrt(i) + 1;  
            for(j = 2; j <= t; ++j)  
            {  
                    if(i % j == 0)  
                            return false;  
            }  
            return true;  
    }  
      
    static ERL_NIF_TERM findPrime(ErlNifEnv *env, int argc, ERL_NIF_TERM argv[])  
    {  
            int n;  
            if(!enif_get_int(env, argv[0], &n))  
                    return enif_make_badarg(env);  
            else  
            {  
                    int i;  
                    ERL_NIF_TERM res = enif_make_list(env, 0);  
                    for(i = 2; i < n; ++i)  
                    {  
                            if(isPrime(i))  
                                    res = enif_make_list_cell(env, enif_make_int(env, i), res);  
                    }  
                    return res;  
            }  
    }  
      
    static ErlNifFunc nif_funcs[] = {  
            {"findPrime", 1, findPrime}  
    };  
    
    ERL_NIF_INIT(etest001, nif_funcs, NULL, NULL, NULL, NULL)
    

      其中erlang的调用如下,C编译完成的叫etest001_nif.so

    load() ->  
            erlang:load_nif("./etest001_nif", 0).  
      
    findPrime(_N) ->  
            io:format("this function is not defined!~n").
    

      我们来统计一下运行时间

    11> timer:tc(etest001, findPrime, [100000]).
    {8994,
     [99991,99989,99971,99961,99929,99923,99907,99901,99881,
      99877,99871,99859,99839,99833,99829,99823,99817,99809,99793,
      99787,99767,99761,99733,99721,99719,99713,99709|...]}

    我们用erlang实现

    myprime(N) ->
        myprime(N+1,3,[]).
    
    myprime(N, N, L) ->
        L;
    myprime(N, X, L) ->
        case isprime(X) of
            false ->
                myprime(N,X+1,L);
            true ->
                myprime(N,X+1,[X|L])
        end.
    
    isprime(1) ->
        false;
    isprime(2) ->
        false;
    isprime(N) ->
        M = erlang:trunc(math:sqrt(N)) + 1,
        isprime(M,2,N).
    
    isprime(M, M, _) ->
        true;
    isprime(M, X, N) ->
        if  N rem X == 0 ->
                false;
            true ->
               isprime(M, X+1, N)
        end.
    

      我们来统计一下运行时间

    12> timer:tc(etest001, myprime, [100000]).  
    {65929,
     [99991,99989,99971,99961,99929,99923,99907,99901,99881,
      99877,99871,99859,99839,99833,99829,99823,99817,99809,99793,
      99787,99767,99761,99733,99721,99719,99713,99709|...]}

    好,现在可以看出erlang使用的时间差不多是使用nif(C语言)的8倍,而且随着这个数的增加,这个倍数应该是越来越大

    有人可能会说,erlang擅长的是并发,你这个没有用并发阿,当然不快,好我们用并发,因为要用并发,而且结果要显示一个,所以肯定要用消息,

    我们下面用并发的试试

    代码如下

    myprime2(N) ->
        Pid = self(),
        _ = [spawn(fun() -> isprime2(Pid, X) end) ||  X <- lists:seq(1,N)],
        myprime_work(N, []).
    
    myprime_work(0, L) ->
        L;
    myprime_work(N, L) ->
        receive
            false ->
                myprime_work(N-1, L);
            X ->
                myprime_work(N-1, [X|L])
        end.
    
    isprime2(Pid, 1) ->
        Pid ! false;
    isprime2(Pid, 2) ->
        Pid ! false;
    isprime2(Pid, N) ->
        M = erlang:trunc(math:sqrt(N)) + 1,
        isprime2(Pid, M, 2, N).
    
    isprime2(Pid, M, M, N) ->
        Pid ! N;
    isprime2(Pid, M, X, N) ->
        if  N rem X == 0 ->
                Pid ! false;
            true ->
               isprime2(Pid,M, X+1, N)
        end.
    

     我们还是看看结果

    13> timer:tc(etest001, myprime2, [100000]).
    {456058,
     [99991,99989,99971,99961,99929,99923,99907,99901,99881,
      99877,99871,99859,99839,99833,99829,99823,99817,99809,99793,
      99787,99767,99761,99733,99721,99719,99713,99709|...]}
    

     

    这个实现的居然比先前的还慢,是先前单进程的(erlang的)6倍左右,是nif(C语言)的48倍左右

    8994 μs(nif,C) ,65929 μs(erlang,单进程),456058 μs(erlang,多进程)

    主要原因消息的成本(消息比较多,一个进程一个消息,还有创建进程的成本)是比计算还高很多~~~

    大家可以在自己的环境试试,erlang的程序也还能优化,可是结果应该不会有大的变化(因为相差太多)~~~

     

  • 相关阅读:
    php数组常用函数
    java中Property类的基本用法
    properties文件不能输入中文
    Eclipse中Outline里各种图标的含义
    Eclipse的工程名有红色的感叹号,工程里面没有显示编译错误
    路径问题
    yum -y install 和yum install 的区别
    Linux下源码安装jdk
    Linux下安装rz、sz命令(文件上传下载)
    scp命令详解—跨服务器复制文件
  • 原文地址:https://www.cnblogs.com/tudou008/p/10972064.html
Copyright © 2011-2022 走看看