newLISP Fan Club

Forum => newLISP in the real world => Topic started by: cormullion on May 15, 2011, 02:31:02 AM

Title: Is FOOP slow or is it just me?
Post by: cormullion on May 15, 2011, 02:31:02 AM
Running this object-oriented FOOP code:


(new Class 'C)
(context C)
(define (C:C) (list (self 0)))
(define (C:hw) (println "hello world"))

(define (C:do_it)
 (let ((i 0))
   (while (< (++ i) 1000000)
       (hw))))

(context MAIN)
(new C 'my-c)
(my-c:do_it)
(exit)


It's trying to be an exact copy of this Python:


class c:
def hw(self):
print 'Hello World!'

def do_it(self):
i = 0
while i < 1000000:
i = i + 1
self.hw()

inst = c()
inst.do_it()


But the newLISP seems very sluggish. Is it some FOOP-related issue that prevents this from being efficient code? (There are obviously many easier ways to accomplish the same thing without FOOP.)
Title: Re: Is FOOP slow or is it just me?
Post by: Lutz on May 15, 2011, 07:18:21 AM
The code is mainly measuring IO speed from 'println' and a badly (Python'ish) written loop in newLISP. Nothing specific to FOOP is happening here.
Title: Re: Is FOOP slow or is it just me?
Post by: cormullion on May 15, 2011, 07:55:11 AM
OK, I agree it's not the best way to do this particular task. But still, I don't think a basic while loop calling a function that prints is so unidiomatic newLISP that we can accept that it's over 10 times slower than Python. 10 times slower than Perl, OK, we know Perl's pretty quick, but not Python... :)



I was convinced that something must be wrong, but if you say not, that's good to know.



Still, it's only 5 times slower than Ruby! :)
Title: Re: Is FOOP slow or is it just me?
Post by: Lutz on May 15, 2011, 08:14:50 AM

> (time (while (< (++ i) 1000000)))
234.431
> (time (while (< $idx 1000000)))
131.081
> (time (dotimes (x 1000000)))
44.608
> (time (for (i 1 1000000)))
44.166


For benchmarking Perl, Python and newLISP see here:



http://www.newlisp.org/benchmarks/
Title: Re: Is FOOP slow or is it just me?
Post by: m i c h a e l on May 15, 2011, 08:27:06 AM
Hi cormullion!



Your constructor:


(define (C:C) (list (self 0)))


... is referencing an object through self, but a constructor doesn't have an object to reference since it's in the process of creating one. Your code doesn't actually create any objects because your constructor wasn't being called. This line:


(new C 'my-c)


... is making a new class called my-c and this:


(my-c:do_it)


... is more like calling a class method (a method belonging to a class, not an object).



To use objects, you could rewrite the code something like this:


(context (new Class 'C))
  ;; we'll use the default constructor
  (define (hw) (println "hello world"))
  (define (do-it) (dotimes (i 1000000) (:hw (self))))
(context MAIN)

(setq my-c (C)) ; we're calling the constructor here and creating an instance
(:do-it my-c)   ; sending the message 'do-it' to the object 'my-c'
(exit)


m i c h a e l
Title: Re: Is FOOP slow or is it just me?
Post by: cormullion on May 15, 2011, 09:29:04 AM
Thanks michael - you bring light into the FOOP darkness.



Lutz: to play devil's advocate for a moment ... surely it's also common to be testing conditions and incrementing counters in loops, rather than knowing in advance exactly how many iterations are required? Also to be fair I think Python also has for iterators.



I was assuming that the order of magnitude difference I was seeing was caused by some error on my part... The result is still surprising to me, but we'll have to accept it...
Title: Re: Is FOOP slow or is it just me?
Post by: Lutz on May 15, 2011, 10:31:18 AM
When correctly benchmarking 'while' and 'for' in Python and newLISP, I cannot see much of a difference.



# while.py
i = 0;
while i < 10000000:
    i = i + 1

# while.lsp
(setq i 0)
(while (< i 10000000)
(++ i 1))

(exit)


~/shootout> time python while.py



real   0m1.946s

user   0m1.924s

sys   0m0.019s

~/shootout> time newlisp while.lsp



real   0m2.591s

user   0m2.573s

sys   0m0.005s



Python about 33% faster using 'while'





# for.py
i = 0;
for k in xrange(1, 10000000):
    i = i + 1

# for.lsp
(set 'i 0)
(for (k 1 10000000)
(++ i 1))

(exit)


~/shootout> time python for.py



real   0m2.717s

user   0m2.696s

sys   0m0.019s

~/shootout> time newlisp for.lsp



real   0m1.712s

user   0m1.694s

sys   0m0.004s



newLISP 58% faster using 'for'



The difference you saw in your code was due to I/O speed difference for a simple 'print' statement with a short string. If you compare real world code examples, I/O speed between Python, Perl and newLISP, the difference is much smaller, Perl most of the time beeing the fastest, then Python then newLISP.



Ps: note that I am using 10,000,000 iterations instead of 1,000,000 to minimize the effect of newLISP's much faster startup time.
Title: Re: Is FOOP slow or is it just me?
Post by: cormullion on May 15, 2011, 10:59:39 AM
OK, that looks good. But then, if


Quotea simple 'print' statement with a short string


can give such a difference in performance, surely there must be some problems there, if it's not related to while loops... Perhaps there are some optimizations to be made in what must be quite old code by now?!



Thanks for your comments anyway - at least we know what the explanation is.