在Python和Erlang中进行分析列表反转时的问题

问题描述

我正在对Erlang的lists:reverse内置函数(BIF)进行性能分析,以查看其随输入大小的扩展程度。更具体地说,我尝试过:

1> X = lists:seq(1,1000000).
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29|...]

2> timer:tc(lists,reverse,[X]).
{57737,[1000000,999999,999998,999997,999996,999995,999994,999993,999992,999991,999990,999989,999988,999987,999986,999985,999984,999983,999982,999981,999980,999979,999978,999977,999976,999975,999974|...]}

3> timer:tc(lists,[X]).
{46896,999974|...]}

4> Y = lists:seq(1,10000000).
[1,29|...]

5> timer:tc(lists,[Y]).
{434079,[10000000,9999999,9999998,9999997,9999996,9999995,9999994,9999993,9999992,9999991,9999990,9999989,9999988,9999987,9999986,9999985,9999984,9999983,9999982,9999981,9999980,9999979,9999978,9999977,9999976,9999975,9999974|...]}

6> timer:tc(lists,[Y]).
{214173,9999974|...]}
好的,到目前为止,似乎反向BIF相对于输入在大约线性时间内缩放(例如,将输入的大小乘以10,并且所花费的时间也增加10倍)。在纯Erlang中这是有意义的,因为我们将使用诸如tail递归之类的东西来反转列表。我想即使是用C语言实现的BIF,用于反转的算法似乎列表也是一样的(也许是因为列表只是以Erlang表示的方式?)。

现在,我想将它与另一种语言进行比较-也许是我已经使用的另一种动态类型的语言。因此,我在Python中尝试了类似的事情-非常明确地注意使用实际列表而不是生成器,我预计该生成器会在此测试中对Python的性能产生积极影响,从而给它带来不公平的优势。

import time

ms_conv_factor = 10**6

def profile(func,*args):
    start = time.time()
    func(args)
    end = time.time()
    elapsed_seconds = end - start
    print(elapsed_seconds * ms_conv_factor,flush=True)

x = list([i for i in range(0,1000000)])
y = list([i for i in range(0,10000000)])
z = list([i for i in range(0,100000000)])

def f(m):
    return m[::-1]

def g(m):
    return reversed(m)

if __name__ == "__main__":
    print("All done loading the lists,starting now.",flush=True)
    print("f:")
    profile(f,x)
    profile(f,y)
    print("")
    profile(f,z)

    print("")

    print("g:")
    profile(g,x)
    profile(g,y)
    print("")
    profile(g,z)

这似乎表明函数加载并运行一次后,输入的长度没有变化,并且反转时间非常快-约0.7µs。

确切结果:

All done loading the lists,starting now.
f:
1.430511474609375
0.7152557373046875

0.7152557373046875
0.2384185791015625

0.476837158203125

g:
1.9073486328125
0.7152557373046875

0.2384185791015625
0.2384185791015625

0.476837158203125

我的第一个天真的猜测是python可能能够识别反向构造并创建诸如反向迭代器之类的东西并返回(Python可以正确使用引用?也许是在这里使用某种优化方法)。但是我认为该理论没有意义,因为原始列表和返回的列表并不相同(更改一个列表不应更改另一个列表)。

所以我的问题是:

  • 我的配置文件技术是否有缺陷?我编写测试时是否偏爱一种语言?
  • 在Erlang与Python中实现列表及其反向操作有何不同,从而使这种情况(Python的运行速度更快)成为可能?

(感谢您的时间)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)