Common lisp 使实例消耗524k字节,耗时4ms

Common lisp 使实例消耗524k字节,耗时4ms,common-lisp,Common Lisp,收益率: (time (make-instance 'Flat-Key :key "hello world" :fragment 1)) 键是: Evaluation took: 0.005 seconds of real time 0.004367 seconds of total run time (0.004333 user, 0.000034 system) 80.00% CPU 22 lambdas converted 11,382,613 p

收益率:

(time (make-instance 'Flat-Key :key "hello world" :fragment 1))
键是:

Evaluation took:  
  0.005 seconds of real time  
  0.004367 seconds of total run time (0.004333 user, 0.000034 system)  
  80.00% CPU  
  22 lambdas converted  
  11,382,613 processor cycles  
  524,032 bytes consed

#<FLAT-KEY ((:KEY "hello world") (:HASH 1308457856027851121) (:BUCKET-INDEX 7)
        (:HASH-AS-MASK "1228937CD01BF9-7-1")) {10045AB573}>
(defclass Flat-Key (Key)
  ()
  (:documentation
   "Keys without any level of nesting as used in conventional hash-tries and
Prokopecs CTrie."))
在Didier Verna CLOS《效率:实例化:关于Lisp的行为和性能》中,第2.1部分国际Lisp会议ILC 2009,2009年3月,美国剑桥。2009年泰尔克会议记录,2009年。(通过提供),Didier Verna在这个时间跨度内测量了数百万次“make-instance”调用

这也是关于
#make-instance
和消费量的,但它似乎在做更高级的事情。而且我认为我不能在我的情况下应用他的建议

tl;博士 使用4插槽类的
#“make-instance
需要2ms-5ms和400k-500k字节,这正常吗?
如果没有,我做错了什么?
如果正常,发生了什么?

这是一个社区答案,它重新组合了各种评论。您可以对此答案做出贡献,并添加关于基准测试的其他建议,不一定针对SBCL


  • 如果函数很快,那么对单个调用进行基准测试可能会产生不可靠的结果。为什么不编译一个函数来生成一个实例N次,然后找到一个值N,给你大约5s的执行时间,然后看看平均值。(丹·罗伯逊)


  • 也可以将代码放在已编译的函数中,而不是直接将其写入REPL。虽然REPL编译输入表单,但SBCL并没有像对函数那样对其进行优化。(伊基斯基)

  • 如果第一个需要调用,它可能会有开销。您可能希望自己调用它,以便从后续调用中计算出此开销

  • 请注意,通过在前面调用
    (sb ext:gc:full t)
    ,您通常会减少结果的差异,从而消除度量中的一个“噪声”源

  • Slime/swank需要交换数据,在使用Slime的空闲Lisp中,数据会随着时间慢慢增加(并在每次gc后收缩)。这种情况不会发生在非黏性环境中。它可能不会对时间产生太大影响,但你永远不会知道


如果第一个make实例需要调用finalize继承,那么它可能会有开销。您可能希望自己调用它,以从后续调用中排除此开销。此外,Slime/swank需要交换数据,并且在使用Slime的空闲Lisp中,动态空间使用会随着时间慢慢增加(并在每次gc后收缩)。这种情况不会发生在非黏性环境中。我不认为这会影响很多“时间”,但你永远不知道。在测量前调用gc。尝试进行大量调用,以获得具有统计意义的结果。同时将代码放入已编译的函数中,而不是直接将其写入REPL。虽然REPL确实编译了输入表单,但SBCL并没有像对函数那样对其进行优化。如果函数速度快,则对单个调用进行基准测试可能会产生不可靠的结果。为什么不编译一个函数,使一个实例
n
次,然后找到
n
的值,给你大约5秒的执行时间,然后看看平均值。@DanRobertson,如果你不介意的话,我将这些注释分组在一个社区答案中。
(defclass Key ()
  ((val :initarg :key
    :reader get-key
    :documentation
    "The value of this Key")
   (hash :initarg :hash
     :initform nil
     :documentation
     "Cached `sxhash` of `key-val`, when nil it can be calculated.")
   (hash-fragment-index :initarg :fragment
            :reader get-fragment-index
            :documentation
            "The level in the trie for which `bucket-index` is valid.")
   (bucket-index :initform nil
         :documentation
         "Cached index into the `CNode's` `Bitindexed-List`."))
  (:documentation
   "Common base of all keys in a Trie"))