Home > Advocacy > Comparing gevent to eventlet

Comparing gevent to eventlet

February 27, 2010

In this post I try to explain why gevent was started and how it is compares to eventlet.

Note: gevent has switched to libev.

History

Bob Ippolito wrote the first version of Eventlet in 2006 but ceased working on it fairly early. Donovan Preston took over the maintenance, together with other folks at Linden Lab where he worked at the time. I became interested in Eventlet in 2008, when I was looking for simpler ways to write networking software than with state machines and callbacks. Greenlet-based Eventlet was ahead of the other options that existed at the time (Python’s native generators, raw greenlet, Corotwine) in terms of features and easiness of use.

The project I worked on already depended on Twisted, so I started integrating the two libraries together. In the process of doing that I discovered a number of bugs in Eventlet and ended up rewriting most of its core. My branch was accepted as the way forward and finally released in 2009 as Eventlet 0.8.11. By that time Donovan had already left Linden Lab and Ryan Williams became the primary maintainer.

In the summer of 2009, I have started a new project where a networking library was going to be a major component. However, Eventlet did not meet a couple of requirements:

  • I needed it to use libevent’s event loop because I had another library (written in C) that used it and I wanted to integrate them together in a single process. Eventlet at the time did not have a working libevent support.
  • I needed socket module to work perfectly as I planned to use Python libraries implemented on top of it through monkey-patching. At the time Eventlet had a few bugs that could cause a socket operation to hang.

I have spent some time working on the pyevent-based hub. The result was not very compatible with the rest of Eventlet due to the fact that its Hub API is geared towards pure Python event loops. Making it work smoothly would require significant changes in the interface and implementation of every other hub. The socket module bugs were also specific to event loop, so even though I fixed them for pyevent, they were still present in every other hub. Not having time for a major rewrite of Eventlet I started a leaner project.

Gevent started as Eventlet with a few bugs fixed and a few features dropped.

The differences

1. gevent is built on top of libevent

Update: since 1.0, gevent uses libev and c-ares.

Libevent is a popular portable event loop. It runs your app using the fastest mechanism available on your system, such as epoll on Linux, and kqueue on FreeBSD. Unlike Eventlet, which maintains its own event loops in pure Python and has only recently gained epoll support, all of gevent’s event loops have been well-tested in real-world, high-scale environments.

The superior performance is one of the benefits of tight integration with libevent, but not the only one. Other benefits are

  • Signal handling is integrated with the event loop.
  • Other libevent-based libraries can integrate with your app through single event loop.
  • DNS requests are resolved asynchronously rather than via a threadpool of blocking calls.
  • WSGI server is based on the libevent’s built-in HTTP server, making it super fast.

2. gevent’s interface follows the conventions set by the standard library

For example, gevent.event.Event has the same interface and the same semantics as threading.Event and multiprocessing.Event but works across greenlets. Eventlet has Event class too, but it uses its own way of doing things for no good reason.

I’ve used the standard interfaces in gevent unless a brand new interface has an obvious advantage. In some cases, where re-implementing the whole class wasn’t necessary, the conventions on the method names set by the standard library were followed.

Here are some of those conventions:

  • wait() does not raise an exception;
  • get() can raise an exception or return a value;
  • join() is like wait(), but for units of execution.

Having consistent interface improves the speed at which we can read and reason about the code. Learning the API becomes easier as well.

Not being constrained by backward compatibility, gevent fixed all the API quirks that Eventlet had. The quality of the API is recognized by the users and Eventlet maintainers. Portions of gevent that are not specific to libevent are being incorporated into Eventlet.

3. gevent is not eventlet

It does not have all the features that Eventlet has. If you already use Eventlet these are the reasons why you might not be able to switch to gevent:

  • If you depend on eventlet.db_pool; gevent doesn’t have a module like that.
  • If you depend on eventlet.processes; there’s no support for subprocesses in the library yet. Here’s an example how to build it yourself.
  • If you depend on Eventlet’s threadpool; gevent does have one currently. Update: there’s a new gevent.threadpool module.
  • If you run Eventlet on Twisted reactor.
  • If you cannot depend on libevent.

Gevent aims to be a small and stable core everyone can depend upon. It delegates the job to libevent whenever possible and provides convenient abstractions for coroutine-based programming. It’s inspired by Eventlet but it’s not a fork and it features a new API. The implementation is simpler and more stable.

Read why others are choosing gevent and what you might encounter when porting from eventlet to gevent.

Thanks to Marcus Cavanaugh, Brad Clements, Nicholas Piël, Andrey Popp and Bob Van Zant for reading drafts of this.

Japanese Translation

Categories: Advocacy Tags: , , ,
  1. Peter Saunders
    February 28, 2010 at 3:18 pm

    You mentioned twisted in your article when working on this with eventlet. Is this a direction you see gevent taking in the future?

    Not having used twisted, I wouldn’t know, but could gevent at some point be used as a reactor core instead of the poll/select reactor cores they have.

    • February 28, 2010 at 5:10 pm

      Twisted has a number of reactors, certainly a lot more than just poll and select. I also think there already is a libevent-based reactor for Twisted, if that’s what you asked about.

  2. April 23, 2010 at 12:12 pm

    Another thing where gevent and eventlet differ is fe the socket implementation. Gevent follows the Python API much closer than Eventlet.

    For example, in Eventlet socket.send() behaves as socket.sendall(). I can imagine that this can cause some problems when monkey patching libraries that rely on socket.send()

  3. February 20, 2011 at 6:25 am

    I appreciate the monkey-patching code for coercing blocking problems away. I called patch_select and now use Twisted like a pro. While it’d be nice to totally transform Twisted a la corotwine, this is something I’d rather see properly built into Twisted rather than monkey-patched. It’s nice to be able to use Twisted as-is (with inlineCallbacks) while taking advantage of gevent+greenlet for what it does best.

  4. February 27, 2011 at 7:40 am

    A week later, here is yet another reason why gevent: a gevent-powered Twisted reactor that lets you run Twisted on gevent and use blocking-style code in Twisted methods :3

    (I would have replied to Peter Saunders, but it’s been a year and he’s probably not going to see it anyway)

  1. No trackbacks yet.
Comments are closed.
%d bloggers like this: