Category: Projects

  • Loomiere: a post-mortem of my favorite code

    Loomiere: a post-mortem of my favorite code

    Fifteen years ago I wrote the code I’m still proudest of, for a product category that no longer exists. This is its story, told now that I’ve finally given the repo a dignified closing README instead of letting it rot quietly.

    2010, when video was hard

    If you’re younger than the problem, here’s the world: web video meant Flash players doing progressive download over plain HTTP — and I do mean your own Flash player, because every video site had to write one; there was no HTML5 <video> coming to your help. Seeking worked by asking the server for the file from an offset (?start=). There was no HLS, no DASH, no adaptive bitrate; CDNs existed but were priced for companies with sales departments.

    If you ran a video site, bandwidth was your business model — every wasted byte was money, and every rebuffer was a lost viewer.

    I ran into this the honest way. My company operated peteava.ro, a Romanian video-sharing site (now defunct, like most of that era), and I had already written one streamer for it — psstream, a PHP extension from 2008. It did the job until it didn’t: none of our servers could hold more than about 150 simultaneous streams without the machine practically freezing.

    That wall is where Loomiere begins.

    First pass: the micro-streamers

    The first Loomiere (0.x) was an exercise in minimalism: a set of tiny micro-streamers — one per format — written in C against dietlibc, statically linked, the MP4 streamer weighing about 21 KB on disk and 120 KB in memory, spawned one-process-per-request under ipsvd/runit.

    It entered production on all of peteava’s streaming servers on Friday, January 29, 2010, at 14:31 (some moments you write down). The same day, a random check on the most strained server showed 653 simultaneous clients where the old streamer had managed 150 — and total bandwidth had dropped by roughly a third, because of the throttle I’ll get to in a moment.

    Two months thinking, two weeks writing

    The 0.x design had a ceiling — one process per connection is honest but profligate — so I rebuilt it. I spent about two months just thinking about Loomiere 2.0’s internals before writing it, and then wrote the whole thing in about two weeks.

    Think long, write short — not always possible, but I’ve been trying to work like that ever since; the thinking is the work, the typing is transcription.

    What I remember from those two months isn’t code at all: it’s the old whiteboard, so full of sketches that at some point I was defending it with my own body from the cleaning lady’s sponge. Improbably, a photo of it survives — the exact spot where the Lua and C universes cross inside the code, coroutines yielding on one side of the line, the event loop deciding on the other:

    What came out: a C core on libev with SMP worker threads (“the hardware should be the only limit”), an in-memory cache, and — the part I’d still defend in any design review — Lua as the configuration and scripting surface. Virtual hosts, URL routing, rewrite logic: all Lua, so wiring Loomiere into an existing site was an afternoon, not a migration.

    And that whiteboard sketch is exactly the machinery being born: each stream lived as a Lua coroutine — a blocking operation yielded it across the line to the C event loop and resumed it on readiness — with spinlocks at the few seams where worker threads had to touch. Thousands of streams juggled in parallel on one machine, in 2010, when Node.js was a year-old curiosity and the async-everything movement it would ignite hadn’t happened yet. It was, and I say this with the full bias of authorship, truly beautiful.

    The throttle (the part worth stealing)

    The economics lived in one mechanism: the VBR-aware bandwidth-conservation throttle. Serve at full speed only until the client holds N seconds of playback ahead of the play-head (default: 20), then pace delivery to the stream’s own bitrate. The subtlety is “seconds”: with variable-bitrate video a byte target is wrong at exactly the moments that matter, so the buffer was tracked in playback time, not bytes. Smooth playback, instant seeks, and — since most viewers don’t finish most videos — dramatically less bandwidth bought for content nobody watched.

    On day one it cut peteava’s streaming bandwidth from roughly 1300 to 900 megabits while serving more clients.

    The numbers

    The run I still grin about was a single SSD-based machine in January 2011 — a 3 GHz Core i7, 12 GB RAM, six 256 GB SSDs, three gigabit NICs:

    6500+ active concurrent streams, 2841 Mbps of traffic, with the SSDs under 20% load.

    Cacti graph from January 2011: 2771.71 Mbps effective bandwidth
    2771.71 Mbps effective bandwidth — the original Cacti capture.
    Monitoring graph from January 2011: 6500+ active concurrent streams
    6500+ active concurrent streams on one machine.

    At that point we hit a wall that wasn’t Loomiere: somewhere between the I/O path and the sockets — interrupts, kernel, mainboard — the CPU saturated while memory and disks idled. \

    My note from that night reads, in its entirety: “Hmm… this is a deep one.” I never did get to the bottom of it; the wall was comfortably above what any single machine needed to do.

    CPU activity graph showing saturation while memory and disks idled
    The wall: CPU saturating while everything else idled. “Hmm… this is a deep one.”

    In steady production the fleet told the real story: Loomiere 2.0 served all of peteava.ro’s video — about 800 TB every month, from 14 servers — and did so for over five years in total.

    And none of it ran in a cloud, because there was no cloud worth the name: every one of those servers was physical iron that someone had to rack, cable, and keep alive (shout-out to Bogdan, who has since turned that craft into his own hosting business).

    Even the best things end

    Loomiere stood on libev, whose documentation contains a section titled — beautifully — “ev_cleanup — even the best things end”. Somewhere in those docs (I’ve never managed to find the exact passage again, but never managed to forget it either) its author left a thought along these lines: you always have the API to kill whatever needs killing — but there is something about a program written so well that, at end-time, all its threads close gracefully on their own… something close to perfect.

    Loomiere delivered on that spectacularly: at one point it ran for three years without a restart — no leaks, and no creeping memory fragmentation either, which at that kind of uptime stops being an implementation detail and becomes a discipline.

    And when asked to stop, it stopped the way the docs dreamed: every watcher, every worker, every connection closing in order, all the way down.

    And the child in me will forever cherish that.

    What happened

    The category was absorbed, the way categories are. nginx shipped its mp4/flv modules and pseudo-streaming became a config flag on a server everyone already ran. Then adaptive streaming (HLS, DASH) and CDNs finished the job. Loomiere’s last release was December 2011 — right about when the ground finished moving.

    Could I revive it? No. The industry has advanced enormously and I’d be fighting monsters — nginx, CDNs, twenty years of protocol evolution — over territory nobody disputes anymore. Reviving it would honor the code less than closing it well does.

    What it left behind

    Three things survived the product, all of them still in use:

    The method: think long, write short. Not always possible — but I’ve been trying ever since, and Krbn, the pencil-rendering engine I released recently, was built exactly that way, fifteen years later.

    The taste: performance as a design property, not an optimization pass; the conviction that software’s job is to get out of the hardware’s way.

    And the lesson I’d offer anyone building infrastructure products: a product built on a protocol era ends with the era. Platforms absorb categories. If your product is a feature of the platform’s future self, your moat is time — spend it accordingly.

    The repo is preserved at github.com/vpalos/loomiere, readable and honest about what it is. Start with options.lua — the whole design philosophy fits in its comments.

    Rest well, old friend. You were fast.

  • Genesis imperfecta (or: I finally built the pencil)

    Genesis imperfecta (or: I finally built the pencil)

    This is not a scan of a pencil drawing. It’s SVG — computed, deterministic, and, in a sense I’ll get to, exact.

    A sphere resting in a gravity well, the sheet's hatching flowing into the dent

    For the past few months I’ve been building Krbn, a small open-source rendering engine that draws 3D scenes the way a technical sketch artist would. It’s a childhood idea. Back then I wanted to call it genesis imperfecta, because what fascinated me was — and still is — the idea of going against photorealism: that a human being conveys more meaning in a drawing than any photorealistic render, precisely by renouncing detail, dropping precision, deliberately introducing imperfections. The catch, of course, is the question hiding inside that sentence: which detail do you drop? Which imperfections do you introduce? That question turns out to be an engineering problem, and a lovely one.

    The inversion

    Most rendering answers “what color is this pixel?” A pencil drawing answers “which lines would an artist draw — and which would they leave out?” So Krbn has no shading model. It derives strokes from geometry and then applies policies to the stroke set:

    • Silhouettes of spheres, cylinders, cones are computed in closed form — they are exact conics; a torus yields its true quartic. No sampling, no meshes pretending to be curves.
    • Hidden lines aren’t z-buffered away; each contour is split analytically into visible and ghosted runs, the way a draftsman keeps the far edge of a box faintly alive.
    • There is no alpha channel. Cross-hatching is inherently see-through — the gaps between strokes reveal what’s behind, exactly like on paper. And the hatching follows each surface’s own curvature field, so form comes from direction, not gradients.
    Two trefoil knots, one hatched along its curvature field, one hatched flat

    Exactness was a deliberate value, not an optimization: intersections are roots of low-degree polynomials, and the degenerate cases — tangent lines, coincident conics, grazing cusps — are treated as the spec, not as edge cases. The reward is output you can trust: the same scene always emits the same, byte-identical, diffable SVG.

    The part stills can’t show

    Hand-drawn wobble is easy. Hand-drawn wobble that survives animation is not: re-randomize per frame and the whole drawing “boils”. In Krbn the wobble is seeded on stable stroke identity — each line carries its jitter with it across frames — so an orbiting camera slides the silhouettes while the lines stay calm:

    A camera orbit of a mixed scene — the hand-drawn lines stay calm, no boiling

    Getting to that calm — persistent stroke identity, hatch that pans with surfaces instead of re-dealing, detail that fades instead of popping — was the hardest part of the project, and my favorite.

    The other experiment

    I’ll say this plainly, because I put it in the README too: Krbn was built with heavy AI assistance, unapologetically. It doubled as an experiment — how far can a carefully directed human–AI collaboration get on a hard rendering problem? “Carefully directed” is the operative phrase: the architecture, the taste, and the standards are mine, written down and enforced (the working brief and the numerical-robustness rules ship in the repo — judge for yourself). The code was reviewed and tested like any other code. The answer to the experiment, as far as I’m concerned: far. Farther than I expected.

    What’s next

    Nothing on a schedule — this is a break-time project and I intend to keep it joyful. But the ideas corner is already growing (stippling as an alternate hatch strategy, colored pencils that stay stroke color and never become a fill model, deliberate temporal decoherence à la “Take on Me” by A-ha), and the repo has an example gallery.

    If you make technical figures, drive a pen plotter, or just share the fascination — come say hello. Or don’t; all is good. The “pencil” exists now, and 12-yer-old me is happy.

  • Loomiere 2.0.1-beta finally out!

    All right! I finally got around to releasing this code to the public. I won’t say much now (since I’m tired) but I will say that this software has been functioning in production environment for over 1 year and a half serving all the video content available on the romanian website http://peteava.ro (about 800 TB of data each month out of 14 servers).

    Some (old) statistics showing it’s power can be found here.

    Source code: https://github.com/valeriupalos/loomiere.

    Warning:
    Any software downloaded from this website is *never* to be associated in any form with pornographic or erotic content! I.E. “Loomiere” must *never* be used to stream pornographic or erotic videos! There are plenty alternatives if you can’t help it.

  • Lua-TTyrant: a TokyoTyrant binding for Lua.

    Some time ago I started a small project to implement a C-to-Lua binding of the TokyoTyrant library, called “lua-ttyrant“. A few days ago, while working with a script that was actually using it, I decided to polish it up, finish it and eventually submit it to be included in the LuaRocks repositories. Given the fact that the “rock” was just accepted by the LuaRocks team, I thought a new post was in order.

    Files

    The lua-ttyrant source code can be found here (among my github repos).
    The lua-ttyrant rockspec can be found here (among all the public Lua rocks).

    Prerequisites

    • TokyoTyant library and headers.
    • LuaRocks.

    Prerequisites on Debian/Ubuntu distros:

    sudo apt-get install libtokyotyrant-dev
    

    Installation

    sudo luarocks install lua-ttyrant
    

    Status

    The binding is in beta for now. Please contribute a ticket if you find anything wrong with it. For anything else please see the doc/DETAILS file. Enjoy! 🙂

  • “Loomiere 2.0 teaser” reloaded

    UPDATE: http://vpalos.com/1165/loomiere-2-0-1-beta-finally-out/

    «Update… Today this machine reached 6500+ active concurrent connections for a total traffic of 2841.19 Mbps (2778.1 output + 63.09 input) while the SSD’s were still below 20% load. Now that’s what I call serious FUN! 😀 Here are some pictures…

    …end!»

    Since my last post about describing the performance of Loomiere in production, quite a few things have happened. I tested a lot and found many things I would like to improve or add, I tried many hardware configurations to see what goes well with what. In short, I have a whole list of things I want to implement as soon as possible and the most important item on this list is to actually launch Loomiere to the public as soon as possible! 🙂

    However, here is a quick update on the performance of Loomiere, but this time with a nice twist: it’s running on a SSD-based machine! Here are some specs:

    • Intel Core I7 3GHz
    • 12 GB RAM
    • 6 x 256GB SSD Kingston
    • 3 x 1 Gigabit Ethernet cards
    • Ubuntu Lucid Lynx with 2.6.37-12-server kernel

    And here are the results after only a few hours from launch (graphs follow):

    • 4500+ active oncurrent connections (streams)
    • 300+ MB/s of throughput (aprox. 2500 Gbps)

    However, at this point we hit a wall: the mainboard or the kernel. I have to dig into this problem further, but from what I could gather so far, it seems that the mainboard or the Linux kernel can’t handle more punishment. Following are the CPU and memory graphs; it is clear that while the memory has no worries, the CPU is hogging! The problem lies somewhere between the I/O operations and the actual sending of data to the sockets (interrupts maybe?). More testing will follow regarding this issue.

    Hmm… this is a deep one.

    So, that’s it for now, I’m going to sleep. Good night :).

  • Loomiere 2.0 teaser

    UPDATE: http://vpalos.com/1165/loomiere-2-0-1-beta-finally-out/

    This article is a quick peek into how Loomiere 2.0 is (currently) serving close to 3k active streams from a single server in production which is restricted to 1.6 Gbps of bandwidth (we are currently negotiating with our ISP to raise this limitation). All these statistics represent a single machine, in real time, over a period of 12 hours, equipped as follows:

    • 2 x Xeon Dual Core (with HyperThreading) at 3.2GHz
    • 16 GB RAM
    • 15 x 1TB HDD (7200rpm)
    • 4 x 1GB NIC’s
    • This system runs on Ubuntu 10.04.1 LTS.

    OK so here are the graphs:

    The graphs may not yet be as stable as I would wish at the moment since I am still testing this setup as well as Loomiere itself, but I think soon I will have a more stable configuration and also some time to comment on these graphs.

    Enjoy! 🙂

  • Loomiere/Stream: Revived!

    UPDATE: /1165/loomiere-2-0-1-beta-finally-out/

    OK folks, things have settled down and we are good to go. After some considerations the legal concerns for Loomiere/Stream are now cleared and gone. The source is now released and will be available indefinitely. Again, this streamer (minimally customized) has already been serving all the video content at http://peteava.ro for 3 full months (for those seeking a demo).

    Source code: loomiere-0.2.1-tar.gz

    Warning:
    Any software downloaded from this website is *never* to be associated in any form with pornographic or erotic content! I.E. “Loomiere/Stream” must *never* be used to stream pornographic or erotic videos! There are plenty alternatives if you can’t help it.

    Just a teaser:
    Fighting the video-streaming problem has taught me very many things which, in turn, led me to realize that I might be able to use a substantially different streaming approach to achieve a massive amount of optimization in this field. So quite soon, I think I’ll have ready a brand new (and far more powerful) streamer that aims at making it possible for a single server to serve many thousands (I am still testing this) of streams simultaneously using commodity hardware. I am not yet settled on whether this project will be commercial, open-sourced or both but I hope to clear this aspect soon as well. Real-world streaming (i.e. before and after) statistics will be made available on release.

    Stay tuned! 🙂

  • Loomiere/Stream – A high performance streaming server

    UPDATE: http://vpalos.com/1165/loomiere-2-0-1-beta-finally-out/

    The Loomiere (0.2.1) code is now freely available under GPLv3.
    Please see this post for an update.

    Are you killing psstream?

    Well, yes! I am sure that many of you already know about psstream (the PHP streaming extension I made a while back). Well, many things happened since then and I came to realize I could do better; a whole lot better actually. As of now the ‘psstream’ project is officially no longer developed (see below). It will remain on the website for some time to come for archiving purposes but that is it.

    But wait, why did you do it?

    For some time now I have be looking into improving the streaming mechanism for a large video-sharing project run by my company. PSStream was a first effort, and it did the job but soon ran into problems. None of our servers was able to properly stream more than 150 clients simultaneously and the resources were grossly wasted, hence, Loomiere/Stream. (more…)