PLUG: Warsaw python meetings
My friends are going to have python presentations in Warsaw. It's going to be a part of PLUG meetings.
Thursday, 29th November 2007, 19:00 at Politechnika Warszawska, sala AL.
More information:
My friends are going to have python presentations in Warsaw. It's going to be a part of PLUG meetings.
Thursday, 29th November 2007, 19:00 at Politechnika Warszawska, sala AL.
More information:
Posted by majek at 13:32 0 comments
Posted by majek at 23:49 0 comments
Labels: Motoman
Everybody knows that Trinity is using nmap.
But what she has to nsock or libevent, well nothing.
Recently I wrote some software using libevent and I'm disgusted. Libevent is poorly documented (except the self-explanatory function names which are suggestive), there are not many examples on the web. Even though I took an effort and wrote few programs.
About a year ago I put my hands on nmap project, I wrote something for nmap's asynchronous networking library nsock.
There are some really interesting differences between these two libraries:
#include <stdlib.h>And very similar nsock code:
#include <event.h>
/*
gcc -Wall event_test1.c -levent && time ./a.out
*/
int counter = 0;
struct timeval tv = {0,0};
struct event ev;
void timer_handler(int fd, short event, void *ud){
event_add(&ev, &tv);
counter++;
if(counter > 1000000)
exit(0);
}
int main(){
event_init();
event_set(&ev, -1, EV_TIMEOUT, timer_handler, NULL);
event_add(&ev, &tv);
event_loop(0);
return(0);
}
#include <nsock.h>Times of execution this programs are very interesting for me. Unbelievably it seems that nsock is more than two times faster!
#include <stdlib.h>
/* Sorry, some magic with compilation. Nsock isn't standalone library yet!
gcc -Wall nsock_test.c -I/home/majek/nmap/nsock/include /home/majek/nmap/nsock/src/libnsock.a -ldnet /home/majek/nmap/nbase/libnbase.a /home/majek/nmap/libpcap/libpcap.a && time ./a.out
*/
nsock_pool nsp; /* global */
int counter = 0;
void timer_handler (nsock_pool nsp, nsock_event nse, void *ud){
nsock_timer_create(nsp, timer_handler, 0 /*ms*/, NULL);
counter++;
if(counter > 1000000)
exit(0);
}
int main(){
nsp = nsp_new(NULL);
nsock_timer_create(nsp, timer_handler, 0 /*ms*/, NULL);
nsock_loop(nsp, 1000000);
return(0);
}
real 0m2.271sNsock average time:
user 0m0.640s
sys 0m1.624s
real 0m0.941sThe "user time" shows that libevent implementation of internal structures is much heavier than nsock. Even that nsock should have more work because it's allocating event structures alone, without users help. The "sys time" should be similar for both libraries, but it's not. Strace is going to reveal the issue:
user 0m0.392s
sys 0m0.548s
# The loop is reduced to 100 iterations.Well, it seems clear that two things are broken in libevent. First, the gettimeofday() is called four times for every event loop iteration, it's unacceptable waste of resources. Second, the epoll() is executed for every event loop, while for nsock even a single select() isn't called. In this particular case, when timer events are registered with Null timeout there isn't a need of executing epoll().
# Data for NSOCK
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
nan 0.000000 0 203 gettimeofday
# Data for LIBEVENT
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
nan 0.000000 0 406 gettimeofday
nan 0.000000 0 101 epoll_wait
nan 0.000000 0 1 epoll_create
nan 0.000000 0 1 epoll_ctl
Posted by majek at 22:07 3 comments
Labels: Algorithms, Asychrony, Linux, Network, Nmap, Performance
So I want to write asynchronous tcp/ip server in python.
I really hate overblown twisted. The thing I like most in Python is simplicity and easiness to read. Well, twisted in my opinion doesn't have this attributes. It's of course my personal feeling, mostly because I don't know twisted. But such statements are making me sick, at first sight I really don't understand what are they for (from core twisted documentation):
internet.TCPServer(7779, IFingerFactory(f)).setServiceParent(
service.IServiceCollection(application))
Traceback (most recent call last):
File "./tights.py", line 37, in
main()
File "./tights.py", line 34, in main
event.dispatch()
File "event.pyx", line 262, in event.dispatch
TypeError: exceptions must be strings, classes, or instances, not type
#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket, signal, libevent
def callback_interrupt(signum, events, event_obj):
libevent.loopExit(0)
def callback_onconnect(fd, events, event):
# hack to avoid passing sock_srv from main()
sock_srv = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
sock, (host, port) = sock_srv.accept()
conn = Connection(sock, (host, port))
class Connection:
def __init__(self, sock, addr):
self.sock = sock
self.addr = addr
self.sock.setblocking(False)
libevent.createEvent(sock, libevent.EV_READ, self.callback_onread).addToLoop()
def callback_onread(self, fd, events, event_obj):
buf = self.sock.recv(4096)
if not buf: # just disconnect
self.sock.close()
return
# Yeah, print!
print "%r %r" % (self.addr, buf)
# reuse current event
event_obj.addToLoop()
if __name__ == '__main__':
# bind.
sock_srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_srv.setblocking(False)
sock_srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_srv.bind(('0.0.0.0', 1111))
sock_srv.listen(5)
libevent.createSignalHandler(signal.SIGINT, callback_interrupt).addToLoop()
libevent.createEvent(sock_srv, libevent.EV_READ|libevent.EV_PERSIST, callback_onconnect).addToLoop()
libevent.dispatch()
Posted by majek at 20:19 2 comments
Labels: Algorithms, Asychrony, Linux, Network, Performance, Python