Skip to content

Implementation notes

Zete Lui edited this page Oct 5, 2013 · 9 revisions

Directories

bin/
  nyara
ext/
  http-parser/        # external repo
  multipart-parser-c/ # external repo
  inc/                # files to include
    kqueue.h
    epoll.h
  nyara.h             # common header in all .c / .cc
lib/
  nyara.rb            # contains autorun code
  nyara/
    hashes/           # hash variants
    patches/          # minisupport
    templates/        # new project template
    view_handlers/    # adapter for erubis/slim/...
    command.rb        # masters the `nyara` command
    nyara.rb          # loads all
spec/
  apps/          # web apps used in test, can be run directly
  performance/   # scripts comparing performance, can be run directly
  raw_requests/  # dumped request raw requests

Major classes and modules

Nyara::NyaraConfig # class for Nyara::Config, it exists only for rdoc
Nyara::Request     # represents request and hides file descriptor
Nyara::Ext         # includes hidden extension methods

LT vs ET

  • Edge Trigger in kqueue - EV_CLEAR
  • Edge Trigger in epoll - EPOLLET

Level trigger has more time spent in system polling, and needs to hand-delete some events.

Edge trigger has less time in system polling, but we need to carefully not lose any events.

With LT

  • for kqueue, need to delete events with EV_EOF
  • for epoll, to prevent from getting events from closed socket (the fd may be duped so close(fd) is not sufficient), should remove event listener when first time get an EPOLLHUP.

With ET

  • We can prevent mis-handling of events

Identifying connection

Every connection creates a new file descriptor

At first I thought file descriptor is enough, but this case fails:

In a previous round, request closes fd, in a second round, fd with the same number is created by accept.

This fail case is identified on linux, causing epoll 100% CPU.

Identify connection with a custom number would be better.

Now nyara is changed to a self-genereated id: Request.rid.

Fiber

rb_protect creates a fiber stack rewinding barrier, using fiber across many rb_protects is not possible.

https://www.ruby-forum.com/topic/195702

Connection: keep-alive

nginx can rewrite connection: close to connection: keep-alive, no need to worry about it.

OOB GC

Ensure enough slots when the process is idle

See https://bugs.ruby-lang.org/issues/8983

Clone this wiki locally