Speed test: Ruby & hash tables vs. newLISP & symbols
Posted: Fri Jun 30, 2006 2:47 am
Most people who adopt newLISP after using awk, Ruby, Perl, or Python are concerned about the lack of associative arrays (hash tables). So I decided to test how well newLISP's symbols in contexts compare to Ruby's hash tables. The task is to parse a file of 3,622,143 bytes that contains letters P--Q of an unabridged dictionary. The first programs simply count the number of unique words and the number of letters in those words. The second pair of programs count the number of times each word occurs.
newLISP:
Ruby:
newLISP:
Ruby:
Keep in mind that Ruby is slower than Python and Perl.
newLISP:
Code: Select all
(set 'start-time (time-of-day))
(while (read-line)
(dolist (word (parse (current-line) {[^A-Za-z]+} 0))
(if (not (empty? word))
(sym word 'Words))))
(set 'middle-time (time-of-day))
(set 'char-count 0)
(dolist (word-sym (symbols Words))
(inc 'char-count (length word-sym)))
(set 'end-time (time-of-day))
(set 'fmt "%-34s%5d\n" )
(print (format fmt "Milliseconds to parse file: "
(- middle-time start-time)))
(print (format fmt "Milliseconds to count characters: "
(- end-time middle-time)))
(print (format fmt "Total milliseconds: "
(- end-time start-time)))
(println (length (symbols Words)) " words; "
char-count " characters")
Code: Select all
def mil( f ); (f * 1000).to_int; end
start_time = Time.now
words = {}
while line = gets
line.split( /[^A-Za-z]+/ ).each{ |word|
words[ word ] = true if not word.empty?
}
end
middle_time = Time.now
char_count = 0
words.each_key{ |word| char_count += word.size }
end_time = Time.now
fmt = "%-34s%5d\n"
puts fmt % [ "Milliseconds to parse file:",
mil(middle_time - start_time) ]
puts fmt % [ "Milliseconds to count characters:",
mil(end_time - middle_time) ]
puts fmt % [ "Total milliseconds: ",
mil(end_time - start_time) ]
puts "#{ words.size } words; #{ char_count } characters"
Code: Select all
Ruby:
Milliseconds to parse file: 11646
Milliseconds to count characters: 121
Total milliseconds: 11767
40821 words; 304947 characters
newLISP:
Milliseconds to parse file: 5538
Milliseconds to count characters: 70
Total milliseconds: 5608
40821 words; 304947 characters
Code: Select all
(set 'start-time (time-of-day))
(while (read-line)
(dolist (word (parse (current-line) {[^A-Za-z]+} 0))
(if (not (empty? word))
(if (sym word 'Words nil)
(inc (sym word 'Words))
(context 'Words word 1)))))
(set 'middle-time (time-of-day))
(set 'word-count 0)
(dolist (word-sym (symbols 'Words))
(inc 'word-count (eval word-sym)))
(set 'end-time (time-of-day))
(set 'fmt "%-34s%5d\n" )
(print (format fmt "Milliseconds to parse file: "
(- middle-time start-time)))
(print (format fmt "Milliseconds to count words: "
(- end-time middle-time)))
(print (format fmt "Total milliseconds: "
(- end-time start-time)))
(println word-count " words; " (length (symbols 'Words))
" unique words")
Code: Select all
def mil( f ); (f * 1000).to_int; end
start_time = Time.now
words = Hash.new( 0 )
while line = gets
line.split( /[^A-Za-z]+/ ).each{ |word|
words[ word ] += 1 if not word.empty?
}
end
middle_time = Time.now
word_count = 0
words.each_value{ |cnt| word_count += cnt }
end_time = Time.now
fmt = "%-34s%5d\n"
puts fmt % [ "Milliseconds to parse file:",
mil(middle_time - start_time) ]
puts fmt % [ "Milliseconds to count words:",
mil(end_time - middle_time) ]
puts fmt % [ "Total milliseconds: ",
mil(end_time - start_time) ]
puts "#{ word_count } words; #{ words.size } unique words"
Code: Select all
Ruby:
Milliseconds to parse file: 11827
Milliseconds to count words: 80
Total milliseconds: 11907
662846 words; 40821 unique words
newLISP:
Milliseconds to parse file: 6930
Milliseconds to count words: 60
Total milliseconds: 6990
662846 words; 40821 unique words