I've written a command-line tool in Racket to analyze the files produced by a 
tool that traces accesses to persistent memory by an application. The traces 
are large: about 5 million records per second of application run time. While 
developing the tool in Racket was a pleasant, productive, and educational 
experience, the execution time of the tool has become an issue. I have some 
ideas of ways to improve the analysis logic, but I think the trace reader may 
perform so slowly that the result would still be unusable.

The trace records are in a binary format. I have a C++ tool that reads the 
binary trace file and outputs them in a simple sxml-ish textual form to stdout. 
I pipe this into my Racket tool, that then uses the standard Racket reader to 
parse the s-expressions arriving on its stdin. I excised all the analysis code 
from from my tool and just benchmarked the performance of the trace reader. It 
can only read about 62,000 s-expressions per second on a 2.4 GHz Xeon E5-2630 
v3 (Haswell) system. I'm using Racket v6.7.

I've provided the trace reader code below. Have I botched something that would 
make it perform so slowly? I'd rather not  have to recode it in C++.

The input to the tool looks like this:

(pmem_flush
        (threadId 140339047277632)
        (startTime 923983542377819)
        (elapsedTime 160)
        (result 0)
        (addr 0x7fa239055954)
        (length 1))
(pmem_drain
        (threadId 140339047277632)
        (startTime 923983542378153)
        (elapsedTime 83)
        (result 0))


The trace record reader code:

#! /usr/bin/env racket
#lang racket

(require racket/cmdline)
(require racket/runtime-path)

;
; apply trace parser to a stream of trace records
;

; lazy stream of all datums from the input port
(define (make-trace-stream in)
  (let ([datum (read in)])
    (if (not (eof-object? datum))
        (stream-cons datum (make-trace-stream in))
        empty-stream)))

; apply a set of trace-stat% classes to the stream of trace s-expressions
; return a trace-state struct containing the statistics of the trace 
(define (map-trace stat%-set in-port)
  (for/fold
           ([sexp-count 0])
           ([trace-record (in-stream (make-trace-stream in-port))])
            (+ sexp-count 1)))

; apply a null set of trace-stat% classes
(define (accumulate-default-trace-stats in-port)
  (map-trace null in-port))

(define (print-accumulated-default-trace-stats in-port)
  (printf "s-expression count: ~a\n" (accumulate-default-trace-stats in-port)))

;;-----------------------------------------------------------------------------
;; command-line parsing

(module+ main
  (print-accumulated-default-trace-stats
   (command-line
    #:args args
    (if (null? args)
        (current-input-port)
        (open-input-file (first args))))))


Best regards,
-Steve

--  
Steve Byan
steveb...@me.com
Littleton, MA



-- 
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 racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to