[iolib-devel] crash with the current iolib

Stelian Ionescu sionescu at common-lisp.net
Tue Jun 5 00:46:04 UTC 2007

On Mon, Jun 04, 2007 at 01:04:13PM +0300, Aycan iRiCAN wrote:
>First I want to thank you for your great effort. I tried to stress the
>current iolib. Attached is a simple HTTP reply generator. I used sbcl
>1.0.5 VM on a 32 bit AMD desktop machine. I used siege with lot's of
>concurrent connections. Here is the first inspection:
I've attached your code which I modified a bit in order to be able to
debug it more easily

>I got 1490 transactions per second. The performance is great (I got
>around 500 trans/sec with a threaded version) but when I repeat the
>test, SBCL crashes silently and eats all my cpu. I don't get any errors
>or some output.
it crashes here too with the latest SBCL, with a memory-fault-error(most
of the time, I also got various types of heap corruption) - I had to
run SBCL directly from the terminal because indeed Slime seems not to be
able to cope with a memory fault in the REPL thread. On my computer SBCL
crashed directly if I run the test for just 7 seconds
I've also tried CMUCL which is a bit sturdier(but essentially it crashes
too), while CLISP had no problems(although it is slower that SBCL or CMUCL):

hechee at blackhole iolib $ siege -b -c10 -t400S http://localhost:8001/
** siege 2.65
** Preparing 10 concurrent users for battle.
The server is now under siege...
Lifting the server siege...      done.
Transactions:		      216139 hits
Availability:		      100.00 %
Elapsed time:		      400.81 secs
Data transferred:	       30.30 MB
Response time:		        0.02 secs
Transaction rate:	      539.26 trans/sec
Throughput:		        0.08 MB/sec
Concurrency:		        9.95
Successful transactions:      216139
Failed transactions:	           0
Longest transaction:	        9.06
Shortest transaction:	        0.00

>Also the :timeout parameter to add-fd should not be nil
>by default, if so I got type errors with lengthy content sizes.
I believe that it's better if the users of the library specify
themselves the timeout both for the simplicity of the library code and
for the fact that it's difficult to select a default timeout that is ok
for everyone

>Is it possible to outperform java io performance?
once the features will all be implemented and we get to optimize the
code, I think it can certainly be done 

(sign :name "Stelian Ionescu" :aka "fe[nl]ix"
      :quote "Quidquid latine dictum sit, altum videtur.")
-------------- next part --------------
(in-package :common-lisp-user)

(declaim (optimize (speed 3) (safety 1)))

(eval-when (:compile-toplevel :load-toplevel)
  (asdf:oos 'asdf:load-op :iolib))

(defpackage :iolib-problem
  (:nicknames :iop)
  (:use #:common-lisp #:net.sockets #:iomux)
  (:export #:start-server #:stop-server))

(in-package :iolib-problem)

(defparameter *server* nil)
(defparameter *event-base* (make-instance 'event-base))
(defparameter *event-loop-thread* nil)
(defparameter *server-event* nil)
(defparameter *handlers* (make-hash-table :test #'eql))
(defparameter +maxconn+ 50)
(defparameter *currcon* 0)

(defun make-server (port)
  (make-socket :address-family :internet :type :stream
               :connect :passive :reuse-address t
               :local-host +ipv4-unspecified+ :local-port port
               :external-format '(:ascii :line-terminator :dos) :ipv6 nil))

(defun close-handler (event-base connection)
  (remove-event event-base (gethash (socket-fd connection)
  (close connection))

(defun make-client-handler (event-base connection request-handler)
  (declare (type function request-handler))
  (lambda (fd evtype)
    (declare (ignore fd))
      ((eq evtype :read)
                (funcall request-handler connection)
                (finish-output connection))
           (close-handler event-base connection)
           (decf *currcon*))))
      (t (close-handler event-base connection)))))

(defun add-connection-handler (event-base connection request-handler)
  (declare (type function request-handler))
  (setf (gethash (socket-fd connection) *handlers*)
        (add-fd event-base (socket-fd connection)
                :read (make-client-handler event-base connection request-handler)
                :persistent t :timeout 1)))

(defun make-listener-handler (event-base listener-socket request-handler)
  (lambda (fd evtype)
    (declare (ignore fd))
    (case evtype
       (loop :do (if (< *currcon* +maxconn+)
                     (let ((connection (accept-connection listener-socket :wait nil)))
                       (cond (connection
                              (add-connection-handler event-base connection request-handler)
                              (incf *currcon*))
                             (t (loop-finish))))
      (otherwise (break)))))

(defun add-single-threaded-server (event-base listener-socket request-handler)
  (add-fd event-base (socket-fd listener-socket)
          :read (make-listener-handler event-base listener-socket request-handler)
          :persistent t))


(defun test-handler (sock)
  (declare (type stream sock))
  (read-line sock)(read-line sock)
  (format sock "HTTP/1.1 200 OK~%Content-Type: text/html~%Content-Length: ~A~%~%~A"
          (length *response-body*) *response-body*))

(defun start-server (port)
  (setf *server* (make-server port)
        *server-event* (add-single-threaded-server *event-base* *server* #'test-handler)
        *currcon* 0)
  (unwind-protect (event-dispatch *event-base*)

(defun stop-server ()
  (remove-event *event-base* *server-event*)
  (close *server*)
  (setf *server* nil
        *server-event* nil))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <https://mailman.common-lisp.net/pipermail/iolib-devel/attachments/20070605/727d4d9e/attachment.sig>

More information about the iolib-devel mailing list