1
(defpackage :cl-csv-test.speed-tests
2
(:use :cl :cl-user :cl-csv :lisp-unit2 :iter))
4
(in-package :cl-csv-test.speed-tests)
6
(defun run-speed-tests ()
8
:package :cl-csv-test.speed-tests
9
:name :cl-csv-speed-tests
10
:run-contexts #'lisp-unit2:with-summary-context))
12
(defun log-time (&optional (time (get-universal-time)) stream)
13
"returns a date as ${mon}/${d}/${y} ${h}:${min}:{s}, defaults to get-universal-time"
14
(multiple-value-bind ( s min h )
15
(decode-universal-time time)
16
(format stream "~2,'0d:~2,'0d:~2,'0d " h min s)))
18
(defun test-log (message &rest args)
19
(format *standard-output* "~&")
20
(log-time (get-universal-time) *standard-output*)
21
(apply #'format *standard-output* message args)
22
(format *standard-output* "~%"))
24
(eval-when (:compile-toplevel :load-toplevel :execute)
25
(defmacro log-around ((log-name message &rest args) &body body)
26
"Logs the beginning and end of a body. ARGS are evaluated twice"
27
(let ((gmessage (gensym "GMESSAGE-")))
28
`(let ((,gmessage ,message))
29
(flet ((msg (&optional tag)
32
(,log-name (msg "BEGIN") ,@args)
35
(,log-name (msg " END") ,@args))))))
37
(defmacro time-and-log-around ((log-name message &rest args) &body body)
38
"Logs the beginning and end of a body. ARGS are evaluated twice"
39
(let ((trace-output (gensym "TRACE-OUTPUT-")))
40
`(let (,trace-output) ;;leave nil so the first log call doesn't print an extra newline
41
(log-around (,log-name ,(concatenate 'string message "~@[~%~a~]") ,@args ,trace-output)
43
(make-array 10 :element-type 'character :adjustable T :fill-pointer 0))
44
(with-output-to-string (*trace-output* ,trace-output)
45
(time (progn ,@body))))))))
47
(defparameter +test-big-file+
48
(asdf:system-relative-pathname :cl-csv "tests/long-test.csv"))
50
(define-test write-big-file ()
52
(time-and-log-around (test-log "write large file test")
53
(with-open-file (s +test-big-file+ :direction :output :if-exists :supersede )
54
(iter (for i from 0 to n)
55
(write-csv-row '("Russ" "Tyndall" "Software Developer's, \"Position\""
56
"26.2" "1" "further columns" "even" "more" "data")
59
(define-test count-big-file-csv-rows ()
61
(time-and-log-around (test-log "read large file test")
62
(read-csv +test-big-file+
63
:row-fn (lambda (r) (declare (ignore r))
68
(define-test read-by-line-and-buffer (:tags '(cl-csv-test::read-until))
69
(let ((cnt 0) (cnt2 0) (cnt3 0))
70
(time-and-log-around (test-log "read large file by lines")
72
(cl-csv::with-csv-input-stream (s +test-big-file+ )
74
(loop while (setf line (read-line s))
76
(end-of-file (c) (declare (ignore c)))))))
78
(time-and-log-around (test-log "read large file by buffer")
79
(cl-csv::with-csv-input-stream (s +test-big-file+ )
81
(with buffer = (make-array 80 :element-type 'character ))
83
(handler-case (setf fill (read-sequence buffer s))
84
(end-of-file () (finish)))
89
(time-and-log-around (test-log "read large file by read-into-buffer-until")
90
(cl-csv::with-csv-input-stream (s +test-big-file+ )
91
(let ((buffer (make-string cl-csv::*buffer-size*)))
94
while (plusp (cl-csv::read-into-buffer-until buffer s))
96
(end-of-file (c) (declare (ignore c)))))))
98
(format lisp-unit2:*test-stream*
99
"~@:_ lines:~D , buffers:~D, buffered-lines:~D~@:_"
102
(define-test collect-big-file-csv-rows ()
103
(time-and-log-around (test-log "read large file test")
104
(read-csv +test-big-file+))
105
nil ; so we dont print 10m to the repl
108
(defun process-csv2 (csv-name process-function )
110
(labels ((row-processor (row)
111
(let ((result (funcall process-function row)))
113
(push result collector)))))
114
(cl-csv:read-csv csv-name :row-fn #'row-processor)
117
(defun return-blanks2 (filename)
118
(labels ((row-checker (row &aux (6th (sixth row)) )
119
(if (string-equal 6th "")
120
(list (first row) (sixth row)))))
121
(process-csv2 filename #'row-checker)))
123
(defun test-pnathan-code2 ()
124
(time-and-log-around (test-log "test-pnathan2 read")
125
(return-blanks2 +test-big-file+)))
127
;; (test-pnathan-code)
128
;; 15:57:18 BEGIN test-pnathan read
129
;; 15:57:21 END test-pnathan read
131
;; 3.480 seconds of real time
132
;; 3.390000 seconds of total run time (3.200000 user, 0.190000 system)
133
;; [ Run times consist of 0.170 seconds GC time, and 3.220 seconds non-GC time. ]
135
;; 8,678,145,157 processor cycles
136
;; 229,327,728 bytes consed