Hi all, First, as a disclaimer, I'm a total Lisp noobie and have been playing with it recently poking here and there. I just tried Hunchentoot and was happy to see how easy it is to use. I also tried to make some preformance benchmarks on static files and compared it with lighttpd. Unsurprisingly lighttpd beat Hunchentoot quite badly, but I see there is still a lot of improvement for hunchentoot. I did some profiling and added a specialized handler that would serve static files using the linux sendfile system call which really improved the performance. Anyway I still see plenty room for improvements and I would like to take a stab at it, so I did some profiling. I'm putting the results in the ML in case someone wants to discuss it and help me figure out whether the speed for this use case can be improved. Details about the benchmark setup follow:
Intel Dual Core 2 2.0 GHz 1 Gb Ram Ubuntu Gutsy 7.10
SBCL version: Hunchentoot version: Lighttpd version: Benchmark program: ab File: 10 mb bitmap Command: ab -n 1000 -c 20 -k http://127.0.0.1/sendfile/1.jpg
Using sendfile system call
| consed | calls | sec/call | name ----------------------------------------------------------- 0.644 | 25,410,696 | 1,002 | 0.000643 | HUNCHENTOOT::GET-REQUEST-DATA 0.453 | 197,900,328 | 6,006 | 0.000075 | HUNCHENTOOT::WRITE-HEADER-LINE 0.435 | 19,617,768 | 1,001 | 0.000435 | HUNCHENTOOT::HANDLE-STATIC-SENDFILE 0.367 | 0 | 1,001 | 0.000367 | HUNCHENTOOT::SENDTHEFILE 0.230 | 53,605,640 | 1,001 | 0.000230 | HUNCHENTOOT:LOG-MESSAGE 0.163 | 36,415,056 | 2,002 | 0.000082 | HUNCHENTOOT::START-OUTPUT ...
Using hunchentoot static folder dispatcher
| consed | calls | sec/call | name ----------------------------------------------------------- 0.678 | 165,618,816 | 5,000 | 0.000136 | HUNCHENTOOT::WRITE-HEADER-LINE 0.556 | 27,725,384 | 1,000 | 0.000556 | HUNCHENTOOT::GET-REQUEST-DATA 0.347 | 45,721,424 | 1,000 | 0.000347 | HUNCHENTOOT::START-OUTPUT 0.266 | 57,833,952 | 1,000 | 0.000266 | HUNCHENTOOT:LOG-MESSAGE 0.247 | 20,982,224 | 1,000 | 0.000247 | HUNCHENTOOT::COMPUTE-LENGTH 0.135 | 12,926,840 | 2,000 | 0.000067 | HUNCHENTOOT::FORMAT-ADDRESS 0.115 | 13,878,936 | 1,000 | 0.000115 | HUNCHENTOOT::ISO-TIME 0.082 | 237,656 | 1,000 | 0.000082 | HUNCHENTOOT::MAKE-SOCKET-STREAM 0.079 | 16,425,808 | 1,000 | 0.000079 | HUNCHENTOOT:RFC-1123-DATE ....
This is my very dirty implementation of the dispatcher function which is shameles rip of hunchentoot's with some minor functions cleaned :
(declaim (inline sendfile)) (define-alien-routine "sendfile" int (out_fd int :in) (in_fd int :in) (offset unsigned-long :in-out) (count unsigned-long :in))
(in-package :hunchentoot)
(defun handle-static-sendfile (path &optional content-type) "A function which acts like a Hunchentoot handler for the file denoted by PATH but uses the sendfile call. Send a content type header corresponding to CONTENT-TYPE or (if that is NIL) tries to determine the content type via the file's suffix." (unless (or (pathname-name path) (pathname-type path)) ;; not a file (setf (return-code) +http-bad-request+) (throw 'handler-done nil)) (unless (probe-file path) ;; does not exist (setf (return-code) +http-not-found+) (throw 'handler-done nil)) (setf (content-type) (or content-type (mime-type path) "application/octet-stream")) (with-open-file (file path :direction :input :element-type '(unsigned-byte 8) :if-does-not-exist nil) (setf (content-length) (file-length file)) (let ((out (chunga:chunked-stream-stream (flex:flexi-stream-stream *hunchentoot-stream*))) (in (sb-sys:fd-stream-fd file))) (send-headers) (force-output out) (sendthefile (sb-sys:fd-stream-fd out) in 0 (content-length)))))
(defun sendthefile (out in off size) (common-lisp-user::sendfile out in off size))
Just for reference, the sendfile dispatcher does some 350 req/s wherea hunchentoots does about 228 req/s on my machine and against 1199.41 req/s that lighttps can serve using the sendfile backend (data for a 993Kb jpg file with 20 concurrency level).
Thanks for your time, V. Seguí
Hi,
On Fri, 21 Dec 2007 16:58:57 +0100, vseguip@gmail.com wrote:
First, as a disclaimer, I'm a total Lisp noobie and have been playing with it recently poking here and there. I just tried Hunchentoot and was happy to see how easy it is to use. I also tried to make some preformance benchmarks on static files and compared it with lighttpd. Unsurprisingly lighttpd beat Hunchentoot quite badly, but I see there is still a lot of improvement for hunchentoot. I did some profiling and added a specialized handler that would serve static files using the linux sendfile system call which really improved the performance. Anyway I still see plenty room for improvements and I would like to take a stab at it, so I did some profiling.
Thanks for the code and the benchmarks, but currently I have no plans to integrate something like this into Hunchentoot.
First, the technical reasons:
1. This is a Linux-only feature, so it won't buy you anything on Windows or OS X. I hear FreeBSD has something similar, but you'll almost certainly need different code to cater to FreeBSD as well. Furthermore, from a quick glance at the first Google results for "sendfile" it is not clear to me if this will work with all filesystems supported by Linux and if it will work if you use a very old Linux installation.
2. Adding this to Hunchentoot in a reasonable way would imply adding FFI code for all supported Lisp implementations - or adding another dependency like CFFI. That's a lot of complexity for such a small improvement.
But, more importantly, the "philosophical" reason:
Do you have a real-world application that you'd like to use Hunchentoot for where you actually expect more than 250 requests per second? If so, it seems that you have a very successful business and I'd be happy to sign a support contract with you and add whatever feature you want to Hunchentoot. If not, I'd rather concentrate on bugfixes, interesting new features, and ease of use.
Improving the speed of static file serving on Linux has a very low priority for me and this will only change if someone convinces me that they can't use Hunchentoot for their project because of this particular omission.
Cheers, Edi.
Hi Edi, Thanks for your quick reply.
Thanks for the code and the benchmarks, but currently I have no plans to integrate something like this into Hunchentoot.
That was not my intention (I would have sent it as a patch using your coding conventions) and it wouldn't make any sense either since it doesn't need to be integrated in Hunchentoot.
But, more importantly, the "philosophical" reason:
Do you have a real-world application that you'd like to use Hunchentoot for where you actually expect more than 250 requests per second? If so, it seems that you have a very successful business and I'd be happy to sign a support contract with you and add whatever feature you want to Hunchentoot. If not, I'd rather concentrate on bugfixes, interesting new features, and ease of use.
Well if I had a successful business requiring that load I would just go along with lighttpd for static files :). My intention is just to learn Lisp, and when I try to learn any language I try to read existing code bases and try to see if I can hack them to do something, be it improving performance, adding features etc. I think I didn't express my intentions well in my opening post so it's really my fault. So I will try to make more concrete questions: why are functions like get-request-data or write-header-line more time consuming the sending the whole file (even when not using "sendfile")? I was trying to seek an explanation for that since I doesn't seem to make much sense from just reading the code, and maybe, just maybe, try to improve performance (I am guessig that those functions are also being called in dynamic requests so it could help there too) as a learning exercise.
Cheers, V. Seguí
@Bob: thanks a lot for your hints, but I was just doing this as an educational exercise in my quest to learn Common Lisp. I do however keep in mind that information in case I ever have the need for it.
On Sat, 22 Dec 2007 18:03:00 +0100, vseguip@gmail.com wrote:
That was not my intention (I would have sent it as a patch using your coding conventions)
OK, that was a misunderstanding on my side then.
Well if I had a successful business requiring that load I would just go along with lighttpd for static files :)
Right, that's what I'd do as well... :)
So I will try to make more concrete questions: why are functions like get-request-data or write-header-line more time consuming the sending the whole file (even when not using "sendfile")?
Dunno, to be honest. I never profiled them as I never really had performance problems so far. This also implies that these functions are so far in no way optimized for performance.
Are they really more time consuming, BTW? I'm not familiar with the output of SBCL's profiler, so maybe you could explain that a bit. Also, I'm wondering if the methodology (sending requests via ApacheBench and then profiling within SBCL) yields correct results.
On 21-Dec-07, at 10:58 AM, vseguip@gmail.com wrote:
Hi all, First, as a disclaimer, I'm a total Lisp noobie and have been playing with it recently poking here and there. I just tried Hunchentoot and was happy to see how easy it is to use. I also tried to make some preformance benchmarks on static files and compared it with lighttpd. Unsurprisingly lighttpd beat Hunchentoot quite badly, but I see there is still a lot of improvement for hunchentoot. I did some profiling and added a specialized handler that would serve static files using the linux sendfile system call which really improved the performance. Anyway I still see plenty room for improvements and I would like to take a stab at it, so I did some profiling. I'm putting the results in the ML in case someone wants to discuss it and help me figure out whether the speed for this use case can be improved. Details about the benchmark setup follow:
Have you looked at using the x-sendfile header?
http://blog.lighttpd.net/articles/2006/07/02/x-sendfile
To make this work you would run hunchentoot behind lighttpd (or apache). I use apache and a reverse-proxy setup for my lisp and ruby stuff and use this header routinely. Nginx has the same functionality but it is invoked differently (or it used to be).
It is easy to use and so a benchmark shouldn't be hard.
Cheers, Bob
---- Bob Hutchison -- tumblelog at http://www.recursive.ca/so/ Recursive Design Inc. -- weblog at http://www.recursive.ca/hutch http://www.recursive.ca/ -- works on http://www.raconteur.info/cms-for-static-content/home/
On 10060 day of my life vseguip@gmail.com wrote:
I did some profiling...
My profiling shows that on SBCL most "slowness" comes from flexi-streams. For example, such low-level method as flexi-streams::unread-char% calls flexi-streams:translate-char that uses with-output-to-sequence. And last macro generates code that create new instance of flexi-stream, and making instances conses very much on SBCL. You may blame either SBCL or flexi-streams (I tend to blame flexi-streams).
unread-char (and unread-char%) is called by chunga quite often.
On Dec 26, 2007 5:27 PM, Ivan Boldyrev boldyrev+nospam@cgitftp.uiggm.nsc.ru wrote:
On 10060 day of my life vseguip@gmail.com wrote:
I did some profiling...
My profiling shows that on SBCL most "slowness" comes from flexi-streams. For example, such low-level method as flexi-streams::unread-char% calls flexi-streams:translate-char that uses with-output-to-sequence. And last macro generates code that create new instance of flexi-stream, and making instances conses very much on SBCL. You may blame either SBCL or flexi-streams (I tend to blame flexi-streams).
Yes, I profiled flexi-streams and chunga and it showed as much, even when using it only for the headers. Is it possible to create a server that doesn't use flexi-streams at all, or can a handler-request actually configure if it want's to use flexi-streams? I know it's possible to bypass it in the handler, but I think it's called anyway in process-connection, get-request-data, etc. In other words, what would I have to mess around in hunchentoot so I can create a flexi-less handler/server?
Cheers, V. Seguí
(*) Note that even when serving an empty file hunchentoot only reaches ~ 287 requests/second on my system, so dynamic pages will "suffer" from this also.
On Wed, 26 Dec 2007 22:27:40 +0600, Ivan Boldyrev boldyrev+nospam@cgitftp.uiggm.nsc.ru wrote:
For example, such low-level method as flexi-streams::unread-char% calls flexi-streams:translate-char that uses with-output-to-sequence.
Can you check with the latest release (0.14.0) of FLEXI-STREAMS and see if it makes a difference for you?
And last macro generates code that create new instance of flexi-stream, and making instances conses very much on SBCL.
What "last macro" do you mean? Or are you referring to WITH-OUTPUT-TO-SEQUENCE?
Edi.
On Dec 30, 2007 12:22 AM, Edi Weitz edi@agharta.de wrote:
On Wed, 26 Dec 2007 22:27:40 +0600, Ivan Boldyrev boldyrev+nospam@cgitftp.uiggm.nsc.ru wrote:
For example, such low-level method as flexi-streams::unread-char% calls flexi-streams:translate-char that uses with-output-to-sequence.
Can you check with the latest release (0.14.0) of FLEXI-STREAMS and see if it makes a difference for you?
Hi Edi, It definitely makes a difference, get-request-data certainly is not on the top list anymore but write-header-line still tops right there (flexi-streams 0.14) using sendfile system call:
ab -n 1000 -k -c 1 http://localhost:8000/test2.jpg
seconds | consed | calls | sec/call | name ------------------------------------------------------------- 0.475 | 199,787,592 | 6,006 | 0.000079 | WRITE-HEADER-LINE 0.276 | 59,215,472 | 1,001 | 0.000276 | LOG-MESSAGE 0.140 | 0 | 1,001 | 0.000139 | SENDTHEFILE
It looks like write-header-line still takes an inordinate amount of time for no good reason so I changed it to first build a string and the output it to the stream:
(defmethod write-header-line ((mod-lisp-p (eql nil)) key value) "Accepts strings KEY and VALUE and writes them directly to the client as an HTTP header line." (let ((header-lines (with-output-to-string (str) (write-string key str) (write-string ": " str) ;; remove line breaks (write-string (regex-replace-all "[\r\n]" value " ") str) (write-string +crlf+ str)))) (write-sequence header-lines *hunchentoot-stream*)))
This seemed to work very well, and now write-header-line is down to tens of millisecond range, (maybe using write-string on the *hunchentoot-stream* was causing a flush on the socket each time?):
seconds | consed | calls | sec/call | name ------------------------------------------------------------- 0.256 | 57,464,072 | 1,001 | 0.000256 | LOG-MESSAGE 0.176 | 0 | 1,001 | 0.000175 | SENDTHEFILE 0.089 | 11,123,696 | 277,277 | 0.0000003 | FLEXI-STREAMS::CHAR-TO-OCTETS 0.084 | 16,824,960 | 1,001 | 0.000083 | RFC-1123-DATE 0.080 | 14,609,960 | 1,001 | 0.000079 | ISO-TIME 0.071 | 818,104 | 2,005 | 0.000035 | FLEXI-STREAMS::SET-CLASS 0.047 | 12,264 | 1,002 | 0.000047 | FORCE-OUTPUT* 0.046 | 0 | 277,277 | 0.0000002 | FLEXI-STREAMS::WRITE-BYTE* 0.035 | 0 | 130,130 | 0.0000003 | (SETF FLEXI-STREAMS::FLEXI-STREAM-LAST-CHAR-CODE) 0.032 | 1,514,000 | 1,001 | 0.000031 | SERVER-NAME-HEADER
Just for the sake of it, I redefined log-messsage to a "do-nothing" function and this is what I got:
seconds | consed | calls | sec/call | name ------------------------------------------------------------- 0.192 | 0 | 1,001 | 0.000191 | SENDTHEFILE 0.139 | 12,404,872 | 1,001 | 0.000139 | HANDLE-STATIC-SENDFILE 0.103 | 4,741,480 | 2,005 | 0.000051 | FLEXI-STREAMS::SET-CLASS 0.100 | 16,327,208 | 1,001 | 0.000099 | RFC-1123-DATE 0.097 | 18,786,488 | 126,127 | 0.000001 | FLEXI-STREAMS::READ-BYTE* 0.074 | 0 | 182,182 | 0.0000004 | FLEXI-STREAMS::WRITE-BYTE* 0.063 | 0 | 130,132 | 0.0000005 | (SETF FLEXI-STREAM-POSITION) 0.055 | 750,888 | 1,002 | 0.000055 | FORCE-OUTPUT* 0.053 | 50,860,872 | 6,006 | 0.000009 | WRITE-HEADER-LINE
Now it seems like rfc-1123-date could do with some optimization, but all in all I'm getting 465 req/sec wich is a very nice performance improvement. Cheers, V. Seguí
On Sun, 30 Dec 2007 14:38:56 +0100, vseguip@gmail.com wrote:
It looks like write-header-line still takes an inordinate amount of time for no good reason so I changed it to first build a string and the output it to the stream
OK, that seems like an easy fix. I'll integrate that into the next release. Thanks.
Now it seems like rfc-1123-date could do with some optimization
You're on SBCL? Try to benchmark RFC-1123-DATE with pretty-printing turned off.
but all in all I'm getting 465 req/sec wich is a very nice performance improvement.
Right. All you need now is a website with 400 visitors per second... :)
Edi.
Hi Edi,
You're on SBCL? Try to benchmark RFC-1123-DATE with pretty-printing turned off.
That sure helped, I'm now in he 510~550 req/sec range. Anyway, is there a more elegant way to turn logging off than simply redefining the method? I think the fact that log-message is locking when logging to a file makes it take a sever performance hit, maybe the use of a logging framework that solves this would be nice.
Right. All you need now is a website with 400 visitors per second... :)
That's a piece of cake, just run apache-bench in a forever loop :).
On a side note, I wanted to comment some refactoring to hunchentoot that I think may make sense. Right now process-connection is a function that takes care of reading from the client, be it via mod_lisp or directly, binding the chunga/flexi-streams if needed and dispatching it. I think a better design would be to make process-connection a generic method on class connection and then implementing methods for mod_lisp/standalone/fastcgi/whatever. Chunga and flexi-streams wrapping could be implemented as mixins so the user can choose to create a FCGI connection with flexi but not chunga, etc. With this we can allow for custom backends to be developed by users so we gain flexibility (and maintainability) at the cost of some overhead when dispatching. What do you think?
Cheers, V Segui
On Sun, 30 Dec 2007 18:55:22 +0100, vseguip@gmail.com wrote:
Anyway, is there a more elegant way to turn logging off than simply redefining the method?
Sure. There are several ways to control this:
http://weitz.de/hunchentoot/#log
You could for example turn access log messages off. Of course, once you have your 300-visitors-per-second website, you probably /want/ logging... :)
I think the fact that log-message is locking when logging to a file makes it take a sever performance hit, maybe the use of a logging framework that solves this would be nice.
Yes, maybe. Is there a mature, stable, well-documented logging framework out there that works with all Lisps supported by Hunchentoot? How would such a framework deal with several threads trying to log at the same time if not with locking?
One could also think of a setup where there's one dedicated logging process and other processes write to the log file by sending objects to its mailbox:
http://cl-cookbook.sourceforge.net/process.html#mailbox
(Or use cl-muproc? Maybe a bit of overkill.)
But that would cancel the support for non-threaded Lisps we have now and it would introduce more implementation-dependent code.
Anyway - not a big priority for me. If it's important for you, I'd suggest you make a detailed proposal, we discuss it here, then you send a clean patch.
On a side note, I wanted to comment some refactoring to hunchentoot that I think may make sense. Right now process-connection is a function that takes care of reading from the client, be it via mod_lisp or directly, binding the chunga/flexi-streams if needed and dispatching it. I think a better design would be to make process-connection a generic method on class connection and then implementing methods for mod_lisp/standalone/fastcgi/whatever. Chunga and flexi-streams wrapping could be implemented as mixins so the user can choose to create a FCGI connection with flexi but not chunga, etc. With this we can allow for custom backends to be developed by users so we gain flexibility (and maintainability) at the cost of some overhead when dispatching. What do you think?
I'm always open for changes which improve flexibility and maintainability and at first sight your proposal sounds fine to me. If you want to implement that, I'd suggest to proceed like I described above.
Edi.
On Dec 30, 2007 6:47 PM, Edi Weitz edi@agharta.de wrote:
On Sun, 30 Dec 2007 18:55:22 +0100, vseguip@gmail.com wrote:
I think the fact that log-message is locking when logging to a file makes it take a sever performance hit, maybe the use of a logging framework that solves this would be nice.
Yes, maybe. Is there a mature, stable, well-documented logging framework out there that works with all Lisps supported by Hunchentoot? How would such a framework deal with several threads trying to log at the same time if not with locking?
One could also think of a setup where there's one dedicated logging process and other processes write to the log file by sending objects to its mailbox:
http://cl-cookbook.sourceforge.net/process.html#mailbox
(Or use cl-muproc? Maybe a bit of overkill.)
But that would cancel the support for non-threaded Lisps we have now and it would introduce more implementation-dependent code.
One file per thread might work, though I suppose it would break down if you had many thousands of threads...
Of course, if you were running behind lighttpd or similar, you could have it doing request logging.
As I (unfortunately :) ) don't see anything like 400 requests per second to my personal projects, this isn't something I'd really be interested in looking into too much myself. Rob
On Sun, 30 Dec 2007 23:05:03 +0000, "Robert Synnott" rsynnott@gmail.com wrote:
One file per thread might work
Well, who wants to read all these log files then?
Of course, if you were running behind lighttpd or similar, you could have it doing request logging.
That's what already happens (with Apache) if you're using mod_lisp.
On Sun, 30 Dec 2007 19:47:06 +0100, Edi Weitz edi@agharta.de wrote:
Yes, maybe. Is there a mature, stable, well-documented logging framework out there that works with all Lisps supported by Hunchentoot? How would such a framework deal with several threads trying to log at the same time if not with locking?
One could also think of a setup where there's one dedicated logging process and other processes write to the log file by sending objects to its mailbox:
http://cl-cookbook.sourceforge.net/process.html#mailbox
(Or use cl-muproc? Maybe a bit of overkill.)
But that would cancel the support for non-threaded Lisps we have now and it would introduce more implementation-dependent code.
Another option would be to make the current way of logging the default but to let the user bypass and/or change this behaviour if he so wishes.
For example by making LOG-MESSAGE a generic function.
Oh, wait, it /is/ already a generic function. And the documentation says:
"LOG-MESSAGE is a generic function, so you can specialize it or bypass it completely with an around method."
Well... :)
Hi,
Edi Weitz edi@agharta.de writes:
Anyway - not a big priority for me.
Maybe you'd want to distribute a TODO (with a ROADMAP?) with Hunchentoot. I think many people would be happy to help you to get those `priorities' done.
Regards.
On Fri, 11 Jan 2008 00:46:40 +0200, Volkan YAZICI yazicivo@ttmail.com wrote:
Maybe you'd want to distribute a TODO (with a ROADMAP?) with Hunchentoot. I think many people would be happy to help you to get those `priorities' done.
Yeah, good idea.
Until I've done that, you can scan the mailing list archives, though... :)
Agreed. And can you put DAV level 2 on the priority list? :)
Thanks,
Cyrus
On Jan 10, 2008, at 2:46 PM, Volkan YAZICI wrote:
Hi,
Edi Weitz edi@agharta.de writes:
Anyway - not a big priority for me.
Maybe you'd want to distribute a TODO (with a ROADMAP?) with Hunchentoot. I think many people would be happy to help you to get those `priorities' done.
Regards. _______________________________________________ tbnl-devel site list tbnl-devel@common-lisp.net http://common-lisp.net/mailman/listinfo/tbnl-devel
On Thu, 10 Jan 2008 16:02:32 -0800, Cyrus Harmon ch-tbnl@bobobeach.com wrote:
And can you put DAV level 2 on the priority list? :)
Oh, I thought Andreas and you were finished with it by now... :)
Edi Weitz edi@agharta.de writes:
Right. All you need now is a website with 400 visitors per second... :)
I totally agree with the position that bugfixes, interesting new features, and ease of use is the main priority.
On the other hand I glad to hear about this performance improvement. It is not only about 400 visitors per second, but also means less resource consumption and possibility to run web server on smaller machine, for example cheap VPN. Also, if we are serving pages with frames, images etc, even several visitors may produce many requests, and with performance improvement they will have better response time.
Several people mentioned that they were surprised by low hunchentoot performance: http://abstractstuff.livejournal.com/2007/06/28/ http://www.newartisans.com/blog_files/lisp.web.servers.php If you remember, I too tested hunchentoot by ApacheBench when running it in SBCL on a VPN with 64 MB of memory and SBCL was killed by linux because of out-of-memory.
But now, we see that simple fix significantly improve performance, that proves robust design of hunchentoot.
So it's good.
Sorry for the long letter.
Happy new year,
-- Anton
On 10069 day of my life Edi Weitz wrote:
Can you check with the latest release (0.14.0) of FLEXI-STREAMS and see if it makes a difference for you?
I see something strange: no difference for unibyte windows-1251, but improvement for utf-8.
I will do proper profiling and statistics later, sorry. Happy New Year! :)
And last macro generates code that create new instance of flexi-stream, and making instances conses very much on SBCL.
What "last macro" do you mean? Or are you referring to WITH-OUTPUT-TO-SEQUENCE?
Yes.
On Mon, 31 Dec 2007 15:58:09 +0600, Ivan Boldyrev boldyrev+nospam@cgitftp.uiggm.nsc.ru wrote:
I see something strange: no difference for unibyte windows-1251, but improvement for utf-8.
Hmm, should've been the other way around. Specifically, I would expect improvements for ASCII and LATIN-1 which is what counts for Chunga's internals.
Edi.
On 10070 day of my life Edi Weitz wrote:
I see something strange: no difference for unibyte windows-1251, but improvement for utf-8.
Hmm, should've been the other way around. Specifically, I would expect improvements for ASCII and LATIN-1 which is what counts for Chunga's internals.
utf-8 output is larger, so difference is more visible, perhaps :)
OK, this is a timing results of simple static benchmark (outputting static Cyrillic string):
| 0.13.1 | 0.14.1 | 0.14.1+ib UTF-8 (13553b) | 43.93 | 45.48 | 56.22 KOI8-R (10725b) | 39.52 | 43.48 | 50.89
Result is number of pages per second, 13553b is size of output in bytes. UTF-8 is faster because conversion function is faster. Number of pages is quite low because my computer is quite old :)
0.14.1+ib is a flexi-stream version with my "patch" (not ready for publication). Actually this patch is loadable file that redefines some classes, methods and functions in flexi-streams and hunchentoot. BTW, it addresses vseguip's WRITE-HEADER-LINE differently, on flexi-streams level.
Currently slowest function on this benchmark is FLEXI-STREAMS::CHAR-TO-OCTETS (mostly because it is called so many times; but there is a room for improvement). On my application slowest function is MAKE-FLEXI-STREAM, because it calls some Hunchentoot's functions that use it. It can be improved too, but, I'm afraid, only with flexi-streams' rewriting.