找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 949|回复: 10

[研讨] 【终极测试】repeat,while,mapcar,foreach到底哪个快?

[复制链接]

已领礼包: 40个

财富等级: 招财进宝

发表于 2017-6-8 10:42:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 newer 于 2017-6-8 11:09 编辑

今天我们来测试下 repeat,while,mapcar,foreach四个函数的执行效率

对 长度32768的表进行测试

1、
  1. (defun c:tt1 ()
  2.   (setq lst '(0 1))
  3.   (repeat 14
  4.     (setq lst (append
  5.                 lst
  6.                 lst
  7.               )
  8.     )
  9.   )
  10.   (defun f-repeat ()
  11.     (setq i 0 len (length lst))
  12.     (repeat len
  13.       (nth i lst)
  14.       (setq i (1+ i))
  15.     )
  16.   )
  17.   (defun f-while ()
  18.     (setq i -1 len (length lst))
  19.     (while (< i len)
  20.       (setq i (1+ i))
  21.       (nth i lst)
  22.     )
  23.   )
  24.   (defun f-foreach ()
  25.     (setq i -1)
  26.     (foreach n lst
  27.       (setq i (1+ i))  ;;元素n直接能用
  28.     )
  29.   )
  30.   (defun f-mapcar ()
  31.     (mapcar
  32.       '(lambda (x)
  33.          (setq i (1+ i)) ;;元素x直接能用
  34.        )
  35.       lst
  36.     )
  37.   )
  38.   (xd::quickbench '(
  39.                     (f-repeat)
  40.                     (f-while)
  41.                     (f-foreach)
  42.                     (f-mapcar)
  43.                   )
  44.   )
  45.   (princ)
  46. )



从表中提出每个元素加以利用,上面的代码效率为:

QQ截图20170608102958.png

上面结果看到,while,repeat比mapcar,foreach慢接近10倍,那真的是 repeat和while的效率要比 foreach,mapcar慢吗?  我们看,上面循环里面,foreach,mapcar循环是直接就得到元素,而 repeat,while都要通过nth 函数获取对位元素,循环中,每次都要从表头开始去读指定的元素,速度是不是慢在这里了?

下面对repeat,while函数改造下,不用nth函数,而是每次都用car   读取表头元素,同时删除掉表头,这样每次的表头都是对应位置的元素,再看看效率。

  1. (defun c:tt3 ()
  2.   (setq lst '(0 1))
  3.   (repeat 14
  4.     (setq lst (append
  5.                 lst
  6.                 lst
  7.               )
  8.     )
  9.   )
  10.   (defun f-repeat ()
  11.     (setq i -1 len (length lst))
  12.     (repeat len
  13.       (setq a (car lst))
  14.       (setq lst (cdr lst))
  15.     )
  16.   )
  17.   (defun f-while ()
  18.     (setq i -1 len (length lst))
  19.     (while (car lst)
  20.       (setq a (car lst))
  21.       (setq lst (cdr lst))
  22.     )
  23.   )
  24.   (defun f-foreach ()
  25.     (setq i -1)
  26.     (foreach n lst
  27.       (setq a n)
  28.     )
  29.   )
  30.   (defun f-mapcar ()
  31.     (mapcar
  32.       '(lambda (x)
  33.          (setq a x)
  34.        )
  35.       lst
  36.     )
  37.   )
  38.   (xd::quickbench '(
  39.                     (f-repeat)
  40.                     (f-while)
  41.                     (f-foreach)
  42.                     (f-mapcar)
  43.                   )
  44.   )
  45.   (princ)
  46. )



测试效率:

QQ截图20170608105425.png

这时候验证了我们的猜测,现在4个函数效率基本一个量级了,多次测试,互有胜负。


测试结论:
1、repeat,while不是如以前常说的效率要比foreach,mapcar慢, 快慢决定循环里面是如何读取表数据,尽量用tt3函数里面读数据的方法,尽量别用nth
2、4个函数总体效率差不多,一个级别上,考虑到编程对表处理的方便程度,首选推荐还是mapcar,因为他返回的还是表,能接着做其他函数的参数继续求值。
3、foreach,repeat,while ,这三个,首推foreach ,repeat,while 用哪个无所谓,看自己的习惯。4、4个循环处理函数的特点:while 可以判断条件中间退出,mapcar经过处理也可以判断条件中间退出,另外两个也能,但代码处理要复杂些。


评分

参与人数 3D豆 +15 收起 理由
sh_h + 5 热心帮忙奖!
/db_自贡黄明儒_ + 5 很给力!经验;技术要点;资料分享奖!
ll_j + 5 很给力!经验;技术要点;资料分享奖!

查看全部评分

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 769个

财富等级: 财运亨通

发表于 2017-6-8 10:52:27 | 显示全部楼层
学习了,谢谢楼主分享!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 769个

财富等级: 财运亨通

发表于 2017-6-8 10:55:42 | 显示全部楼层
看到楼主的签名里有“晓东开源通用LISP函数库0418下载“
想请教一下,为什么我的加载不了,提示如下:
晓东通用LISP函数库Build 2017.06.08加载完毕...; 错误: no function definition:
xdrx_matrix_identity

不好意思,实在不知道问谁,如果觉得不合适,告诉我一声,我删了就是!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

 楼主| 发表于 2017-6-8 11:01:06 | 显示全部楼层

下载 XDRX API 安装,然后如果你看到晓东通用LISP函数库的版本比 API下载里面带的通用LISP函数库新,你就下载通用LISP函数库覆盖到 XDRX API的SYS目录下。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1268个

财富等级: 财源广进

发表于 2017-6-8 11:12:09 | 显示全部楼层
本帖最后由 st788796 于 2017-6-8 11:14 编辑

几个函数不能单纯的比较效率,要看使用环境,mapcar 在需要返回表的时候是不二选择,省去了重新构造,如果表循环后不需要了,while + cdr 是首选,foreach 在遍历表数量不大的时候简便,效率也不低

程序的整体运行效率不能只看几个步骤,对变量的使用要综合考虑
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 769个

财富等级: 财运亨通

发表于 2017-6-8 11:18:33 | 显示全部楼层

谢谢N版,单纯的只加载函数库不行是吗?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

 楼主| 发表于 2017-6-8 11:22:57 | 显示全部楼层

等下个版本更新的。
其实,通用LISP函数库配上XDRX API才最大发挥。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 769个

财富等级: 财运亨通

发表于 2017-6-8 11:40:10 | 显示全部楼层

OK! 非常感谢!!!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2017-6-8 12:31:26 | 显示全部楼层
本帖最后由 wowan1314 于 2017-6-8 12:56 编辑

帮忙测试下这个! 循环套循环。循环次数为递减数列,总次数N+(N-1)*(N-2)/2  这种情况急需了解那个写法能省点时间。
  1. (defun c:t11 (/ lst lst1 lst2 tmapc tfore twhil)
  2.     (setq lst '(0 1))
  3.     (repeat 10
  4.         (setq lst
  5.             (append
  6.                 lst
  7.                 lst
  8.             )
  9.         )
  10.     )
  11.     (princ (length lst))
  12.         (defun tmapc (lst / lst1 lst2)
  13.             (setq lst1 lst)
  14.             (mapcar
  15.                 (function
  16.                     (lambda(x)
  17.                         (mapcar
  18.                             (function
  19.                                 (lambda(y)
  20.                                     (setq lst2 (cons (list x y) lst2))
  21.                                 )
  22.                             )
  23.                             (setq lst1 (cdr lst1))
  24.                         )
  25.                     )
  26.                 )
  27.                 lst
  28.             )
  29.             lst2
  30.         )
  31.         (defun tfore (lst / lst1 lst2)  
  32.             (setq lst1 lst)
  33.             (foreach x lst
  34.                 (foreach y (setq lst1 (cdr lst1))
  35.                     (setq lst2 (cons (list x y) lst2))
  36.                 )
  37.             )
  38.             lst2
  39.         )
  40.         (defun twhil (lst / lst1 lst2 X)
  41.             (while lst
  42.                     (setq x (car lst) lst1 lst lst (cdr lst))
  43.                 (while (setq lst1 (cdr lst1))
  44.                    (setq lst2 (cons (list x (car lst1)) lst2))
  45.                 )
  46.             )
  47.             lst2
  48.         )
  49. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 40个

财富等级: 招财进宝

 楼主| 发表于 2017-6-8 18:02:54 | 显示全部楼层

测试结果:

  1. (defun tmapc (lst / lst1 lst2)
  2.   (setq lst1 lst)
  3.   (mapcar
  4.     (function
  5.       (lambda (x)
  6.         (mapcar
  7.           (function (lambda (y) (setq lst2 (cons (list x y) lst2))))
  8.           (setq lst1 (cdr lst1))
  9.         )
  10.       )
  11.     )
  12.     lst
  13.   )
  14.   lst2
  15. )
  16. (defun tfore (lst / lst1 lst2)
  17.   (setq lst1 lst)
  18.   (foreach x lst
  19.     (foreach y (setq lst1 (cdr lst1))
  20.       (setq lst2 (cons (list x y) lst2))
  21.     )
  22.   )
  23.   lst2
  24. )
  25. (defun twhil (lst / lst1 lst2 X)
  26.   (while lst
  27.     (setq x    (car lst)
  28.           lst1 lst
  29.           lst  (cdr lst)
  30.     )
  31.     (while (setq lst1 (cdr lst1))
  32.       (setq lst2 (cons (list x (car lst1)) lst2))
  33.     )
  34.   )
  35.   lst2
  36. )
  37. (defun c:t11 (/ lst lst1 lst2)
  38.   (setq lst '(0 1))
  39.   (repeat 10 (setq lst (append lst lst)))
  40.   (xd::quickbench '((tmapc lst) (tfore lst) (twhil lst)))
  41.   (princ)
  42. )



搜狗截图20170608180145.png
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2017-6-8 19:59:45 来自手机 | 显示全部楼层
还是得mapcar啊, 上次特意把mapcar换成foreach,吃力不讨好啊
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-4-18 13:45 , Processed in 0.460467 second(s), 58 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表