A while ago, I started a thread about whether Rust or C would be a better 
complement to Racket. After much more Rust research/coding, I got very tired of 
fighting the compiler, so I decided to blow the dust off my C skills (I haven't 
done any serious coding in C since 1996), and code up the app in C.

In about 2.5 hours, I had coded as much of the app in C as had taken many more 
hours in Rust and it was about 2.5x faster and *much* easier to understand. I 
knew exactly what I wanted to do for maximum performance, but I found myself 
constantly fighting Rust. I've concluded that, for me, C is a better complement.

Anyway, the purpose for this post is to ask for some assistance in getting the 
best performance out of my Racket code. After choosing a different soundex 
algorithm, I was a little disappointed in the following runtime numbers for 
identical functionality:

Racket = 10.3s
Ruby = 7.61s
C = 0.472s

Those are numbers for parsing 200K records in a fixed width format to create a 
postgres bulk input file. The real data contains 45+M records, so speed is a 
consideration (e.g. 1.8 min. for C vs. 38.6 min. for Racket)

It's the fact that Racket is currently slower than Ruby which is bugging me. 
Despite my rusty (no pun intended) C skills, I was able to hack a version that 
does zero heap allocation and is pretty speedy, so I wouldn't expect Racket to 
get close to it. On the other hand, I *would* definitely hope the Racket 
version can beat the Ruby version.

Here are the programs:

C: https://gist.github.com/lojic/4369d9d57eb775296c92

Ruby: https://gist.github.com/lojic/2b91fde8e6bbb7bab1cd

Racket: https://gist.github.com/lojic/f306104846d516761952

They have identical output (I measured through the first 4M input records), and 
they are very similar (same functions, etc.) in style.

Latest profile output from Racket (using open-output-nowhere as suggested by 
Vincent):

https://gist.githubusercontent.com/lojic/db6e02d0d9d88e1d5ced/raw/1002b6e6ee14f2c59b067abe6eac0488a3f2dc7a/profile.txt

Earlier today, I had a hacked up Racket version with manual loops, etc., but 
then I thought that I really shouldn't have to resort to that to beat Ruby, so 
I returned the Racket code to a form that was most similar to Ruby. For example:

Ruby:

  def self.parse_string line, beg, len
    line[beg,len].gsub("\\", '').strip
  end

Racket:

(define (parse-string line beg end)
  (string-trim (string-replace (substring line beg end) "\\" "")))

But I think the Ruby runtime is a little more optimized currently. In 
particular, I suspect string-replace vs. gsub, string-trim vs. strip, etc.

The real fun will come when I use a places version of the Racket code, but I 
want to get decent linear speed before parallelizing.

Ruby has no JIT, and both Ruby and Racket of C runtimes, so there doesn't seem 
to be any fundamental reason why similar code shouldn't perform better in 
Racket.

By the way, I compared Racket 6.2.1 with 6.3 and the latter is 10.4% faster for 
this app, so that was encouraging.

Any help is greatly appreciated!

Brian

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to