william_os4y (william_os4y) wrote,
william_os4y
william_os4y

Libevent has pure http API

It's now long time since my last post.

This surely does not means that I'm stopping FAPWS, at contrary I'm more and more convinced that one of the beauty of Python reside in his gluing capabilities.
This observation is probably not new to lot of people, but for my personal case it's better now than never ;-), no ?

After that small philosophical intro, please go back to our main interest: integrate libevent within the python world.
What's great with libevent is that since several release, they have introduced several HTTP low level APIs: send_reply, send_error, ...
I've tried to use them thanks to pyrex, ctype and swig.

With every of those tools I'm facing issues, problems, ... to get a webserver working correctly.
Because I want FAPWS to be light, efficient and stable, I don't like the idea to add layers on which I don't have too much control. Hoooooo, I'm already hearing some voices ;-). The point is not linked with those tools, but more to my competencies to be able to have them working correctly. Indeed, when you are new to C (which is my case) and try to understand how to use swig, trust me, this is not piece of cake.
Thus I'll use the simple, low level Python API for this project. This will be a way for me to learn C and C API of Python.


Will it be easy to learn C from Python ?

We will see.
Any how, any helps are welcome ;-).





Here after, you can see a minimalist webserver serving the famous "Hello World!":
import ctypes
import sys

libevent=ctypes.cdll.LoadLibrary('libevent.so')

def root_handler(req, *arg):
    #print "got request:", req
    libevent.evbuffer_new.restype=ctypes.c_void_p
    #Build a buffer and put page content into it
    buf=libevent.evbuffer_new()
    libevent.evbuffer_add_printf.argtypes=[ctypes.c_void_p, ctypes.c_char_p]
    libevent.evbuffer_add_printf(buf,"Hello world!\n\n")
    #send the buffer with a return code of 200
    libevent.evhttp_send_reply.argtypes=[ctypes.c_void_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_void_p]
    libevent.evhttp_send_reply(req, 200, "OK", buf)
    return 1


    
def main():
    #We just initialise and give the server address and port
    libevent.event_init()
    libevent.evhttp_start.argtypes=[ctypes.c_char_p, ctypes.c_short]
    libevent.evhttp_start.restype=ctypes.c_void_p
    http=libevent.evhttp_start('0.0.0.0',8080)
    #we lik the call to root_handler at a request of "/"
    FUNC=ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p)
    libevent.evhttp_set_cb.argtypes=[ctypes.c_void_p, ctypes.c_char_p, ctypes.c_void_p]
    libevent.evhttp_set_cb(http,"/",FUNC(root_handler), None)
    #we loop and wait events ;-)
    libevent.event_dispatch()
    #we close the loop
    print "end loop main" 
    libevent.evhttp_free.argtypes=[ctypes.c_void_p]
    libevent.evhttp_free(http)

if __name__=="__main__":
    main()

Note: I don't know exsactly why, but the server does not stop when you hit "-c". You must kill it ;-(.

Amazingly, I'm able to get 1700#/sec on my 1.2Ghz Athlon.



Annexes:

[myhost ~]$ ab -n2000 -c10 http://127.0.0.1:8080/
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)

Server Software:
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /
Document Length:        14 bytes

Concurrency Level:      10
Time taken for tests:   1.170227 seconds
Complete requests:      2000
Failed requests:        0
Write errors:           0
Total transferred:      196000 bytes
HTML transferred:       28000 bytes
Requests per second:    1709.07 [#/sec] (mean)
Time per request:       5.851 [ms] (mean)
Time per request:       0.585 [ms] (mean, across all concurrent requests)
Transfer rate:          163.22 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       3
Processing:     2    5   2.5      4      15
Waiting:        1    5   2.6      4      15
Total:          2    5   2.5      4      15

Percentage of the requests served within a certain time (ms)
  50%      4
  66%      4
  75%      7
  80%      7
  90%      9
  95%     11
  98%     13
  99%     14
 100%     15 (longest request)
[myhost ~]$             
Subscribe

  • Bux fixe in Fapws3

    First of all Fapws3 is not dead :-). I read some people saying that the project is no more updated and thus, should be dead. This is not true !!!…

  • Fapws3-11 is out

    Despite what said in February, I decide to release a new version of Fapws3 for Python-2.x. Indeed, thanks to several testors (Blacknoir, Wigunawan)…

  • Fapws3-0.10 is out

    Despite lot of progress on the python3 branch, I propose a new release of Fapws3 for python2.x. Indeed, since 1 year (date of the last stable…

  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 5 comments