2014-02-20-01-ファンクタの悩み - 2 - project-enigma

2014-02-20-01-ファンクタの悩み - 2

>> Site top >> weblog >> 月別アーカイブ >> 2014年02月のlog >> 2014-02-20-01-ファンクタの悩み - 2

最終更新日付:2014/02/20 23:50:00


ファンクタの悩み - 2

2014 年 02 月 20 日

前回からの続き。

とりあえず、ファンクタの値渡しを模倣するために CLOS の使用を模索し始めた。今回は、ちょっと心配なパフォーマンスを調べてみようという話。

まぁ自分から見れば Lisp はまだ外国語なので、何が効率が良いのかとかは試してみないとわからない。そんなわけで、試しに動かしてみましょうということで書いたのが以下のコード。まずは比較のための関数版。単純にパラメータを2倍する。

(locally (declare (optimize speed))
  (defun foo-function (n)
    (declare (type fixnum n))
    (the fixnum (* 2 n))))

で、以下が同じことをするファンクタ版。functor-copy が実際にはコピーを作成していないが、これは foo-functor が状態を持たないからだ。

(defclass foo-functor () ())

(defmethod functor-copy ((func foo-functor))
  func)

(locally (declare (optimize speed))
  (defmethod unary-function ((func foo-functor) arg)
    (declare (type fixnum arg))
    (the fixnum (* 2 arg))))

これらを指定した回数だけコールするための2つの関数を用意する。

(locally (declare (optimize speed))
  (defun func-invoke-test (fnc n)
    (declare (type fixnum n))
    (do ((i 0 (incf i)))
        ((<= n i) nil)
      (declare (type fixnum i))
      (funcall fnc i))))

(locally (declare (optimize speed))
  (defun method-invoke-test (fnc n)
    (declare (type fixnum n))
    (do ((i 0 (incf i)))
        ((<= n i) nil)
      (declare (type fixnum i))
      (functor-invoke fnc i))))

で、これらをそれぞれ1億回ずつコールしてみるわけだ。関数の直接コールと、functor-invoke 経由での関数コール、そして functor-invoke 経由でのファンクタコールの3種類だ。

(let ((count 100000000))
  (time (func-invoke-test #'foo-function count))
  (time (method-invoke-test #'foo-function count))
  (time (method-invoke-test (make-instance 'foo-functor) count)))

実行したのは Windows 版の SBCL 64bit 環境。結果は以下のとおり。

Evaluation took:
  0.873 seconds of real time
  0.858006 seconds of total run time (0.858006 user, 0.000000 system)
  98.28% CPU
  2,081,088,036 processor cycles
  0 bytes consed
 
Evaluation took:
  1.779 seconds of real time
  1.778412 seconds of total run time (1.778412 user, 0.000000 system)
  99.94% CPU
  4,273,856,574 processor cycles
  0 bytes consed
 
Evaluation took:
  1.342 seconds of real time
  1.341609 seconds of total run time (1.341609 user, 0.000000 system)
  100.00% CPU
  3,224,172,645 processor cycles
  0 bytes consed

なんとまぁ、関数コールの方が速いのは予想通りだが、functor-invoke も思ったほど遅くはない。それよりなにより、同じ functor-invoke ではクラスインスタンスの方が関数コールよりも速いではないの。これは予想外だった。

‥‥‥続きは(あれば)次回以降。

 

コメント

このページにコメントする

 

このページのタグ

Page tag : STLとその移植

 

 


Copyright(C) 2005-2017 project-enigma.
Generated by CL-PREFAB.