6 ms·
I mean there was lighttpd before nginx and they have/had pretty similar structures, weights, etc. I feel like I knew at one point why it got so thoroughly supp
by stormbrew 5y ago
I mean there was lighttpd before nginx and they have/had pretty similar structures, weights, etc.
I feel like I knew at one point why it got so thoroughly supplanted by nginx but I don't remember now why that happened.
- simonw 5y agoThe performance engineering in NGINX back then was really quite something. This classic 2007 tutorial starts by pointing out that NGINX parses the HTTP verb by looking at the second letter first, so that if it's O it knows to check for POST or COPY! https://web.archive.org/web/20070505051653/http://www.riceonfire.org/emiller/nginx-modules-guide.html https://web.archive.org/web/20070505051653/http://www.riceon...
- danachow 5y agoDoes it really look at second letter first or is that snippet taken out of context (it isn’t implied that it does in that email, just that it doesn’t use a library function) ? Since most requests are GET it still makes sense to handle that case first. Though after trying to common cases looking at the second letter for the P subcases may save some branching.
- MaxBarraclough 5y agoDoing Boyer and Moore proud. I think that if you want to support all verbs, you face at least 3 'ambiguities' whether you first check the first, second, or third character of the string. (It must be at most the third, as the shortest verbs are 3 characters long.) First checking the first character is ambiguous between POST, PUT and PATCH. First checking the second character is ambiguous between HEAD, DELETE, and GET. First checking the third character is ambiguous between GET, PUT, OPTIONS, and PATCH. [0] edit As danachow points out, the verbs are not all used with the same frequency. If real-world performance is the goal we'd presumably want to optimise for the GET case, which presumably means first checking the first character, as the 'G' is unique to GET. [0] https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
- stormbrew 5y agoSeems likely an optimal algorithm could probably get there just looking sequentially at the first three letters in order. Would be an interesting code-golf.
- sseagull 5y agoA bit of a micro-optimization, but couldn’t you interpret 4 bytes (including the trailing null on the three-letter verbs) as a 32-bit unsigned int and then do integer comparisons or a case statement?
- dlsa 5y agoYou could add a computed goto to really spice things up.
- stazz1 5y agocall it "adventure plumbing"
- morelisp 5y agoThis is close to what nginx does today, if your platform supports unaligned reads. The check for 'O' is a specific fast-path only for HEAD, most others are done via ordinary comparisons.
- legulere 5y agoNGINX does exactly that (after finding the space character after the verb): https://github.com/nginx/nginx/blob/7587778a33bea0ce6f203a8c4de18e33f38b9582/src/http/ngx_http_parse.c#L38 https://github.com/nginx/nginx/blob/7587778a33bea0ce6f203a8c... There are several points to note: This trick only works if the architecture supports unaligned memory access. Macros are used instead of functions, so you don't have to rely on the compiler to do inlining. The shifts and ors should get optimized out by the compiler. I once tried something similar in C#, but sadly the JIT doesn't do that optimization.
- 5y ago
- zxcvbn4038 5y agoYes, nginx code is something you spend a lot of time studying and hope one day you can do as well.
- patcon 5y agoNice! I can't be the only one who went looking and spent way to much time trying to acquaint myself with c++ :) Here's there I ended up: https://github.com/nginx/nginx/blob/363505e806feebb7ceb1f9edb0e3f75c1253384f/src/http/v2/ngx_http_v2.c#L3580 https://github.com/nginx/nginx/blob/363505e806feebb7ceb1f9ed... PS, I'm not totally sure, but they definitely use the count of letters as an optimization, and it seems they increment the bits associated with each type, so the order of the bits behind each NGX_HTTP_GET etc seems to matter...! https://github.com/nginx/nginx/blob/67d160bf25e02ba6679bb6c3b9cbdfeb29b759de/src/http/ngx_http_request.h#L28-L44 https://github.com/nginx/nginx/blob/67d160bf25e02ba6679bb6c3... Someday I will understand :)
- Brybry 5y agoIt's been a while since I have C/C++'d so some of my terminology is probably wrong. ngx_http_v2_parse_method iterates through all the tests, starting with the first test (GET). They compare request method string length to test string length then on matching lengths compare each character in the request method string to the test string. Fully matching strings set the request method numerical value from the test value and returns OK. Any non-matching characters GOTO the next test. After that it does a sanity check on the request method string characters (A to Z or _ or -) and returns OK or DECLINED as appropriate. For the macros defining the HTTP method numerical values I think they're set up that way as bitmasks for bitwise operations. For example, they do things like[1] if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) Here HTTP request method value is bitwise AND against (0x00000002 OR 0x00000004) Any non-zero value here would be true and any zero value is false. So if the request method bit value AND matches either GET or HEAD bits then this conditional is false. [1] https://github.com/nginx/nginx/blob/a64190933e06758d50eea926e6a55974645096fd/src/http/modules/ngx_http_stub_status_module.c#L92 https://github.com/nginx/nginx/blob/a64190933e06758d50eea926...
- morelisp 5y agoThese tricks are cute, but at the time nginx's performance came from much more fundamental design decisions. First, the async model was literally years ahead of Apache. It leaned heavily on interfaces like epoll to manage large connection pools with a small number of processes, while Apache still used a thread or process per connection. Second, it removed exactly the right features - those with minimal benefit and high performance impact. The classic example is .htaccess, which adds (at least) one stat to every single request, but in practice was only needed for the horrible multi-tenant LAMP reseller setups of the day - everyone else was fine with static centralized configuration.
- stormbrew 5y agonote: this thread is about nginx and lighttpd. I don't think anyone is under any illusions that apache was way behind the curve either of those were setting.
- e12e 5y agoMore on nginx vs apache here, for those interested: The Architecture of Open Source Applications - volume II - nginx: https://www.aosabook.org/en/nginx.html https://www.aosabook.org/en/nginx.html
- fomine3 5y agoFor who want to check current implementation: https://github.com/nginx/nginx/blob/429150c1fa78317bdb19de380ce709651dbc042c/src/http/ngx_http_parse.c#L142 https://github.com/nginx/nginx/blob/429150c1fa78317bdb19de38...
- Rebelgecko 5y agoFrom my limited experience, lighttpd has non-stellar documentation and the community (including devs) is kinda rude. nginx has better documentation and a much more welcoming support community. At least for the tasks I use it for (proxying a bunch of random services on a home server), the syntax is a lot easier than lighttpd and it's easier to bring in goodies as modules that would require recompilation on the lighttpd side. It might be a bit of a chicken-and-egg problem, but the nginx binaries are also a lot of up to date in the package managers I used. On a raspberry pi I ended up needing to compile from source to get a modern version, which got kinda annoying.
- wink 5y agoNot sure which year (decade? :P) you're talking about but in the beginning (before 2010, maybe 2007-08?) Jan was still kinda involved in the German PHP scene and I can't imagine that to be true, I only remember good interactions and we were one of the heaviest users of lighttpd back then. But the docs were never that great, and it seemed to be a one man show, later with a very small team, that's when I think it stalled and only picked up pace years later. But there indeed came a time (maybe 2010ish?) where nginx took the lead with gread strides and most people (even the die-hard fans) mostly moved to nginx, that's about when it was clear that it would probably win and stay for the forseeable future. Back in those circles at least (see some other comments for the PHP FPM story) Apache was only kept for setups with lots of different other dependencies, like mod_svn or webdav, if you "only" needed a webserver to front PHP it was nginx. I also remember many people holding out on adopting Apache 2.2 for a looong time.
- mwcampbell 5y agoI used lighttpd from 2007 until early 2009. Then the company I was working for at the time went to managed hosting for about a year, and during that time, we had to use Apache (possibly even with the prefork MPM). When we decided to go back to self-managed dedicated servers in early 2010, I chose nginx. What I remember from that time was that nginx was rising in popularity, and it was being used by WordPress.com. Also, unlike the 2007 setup, this early 2010 setup had a load balancer with three application servers behind it (using FastCGI I think), and if I remember correctly, it was easier to do that with nginx than lighttpd.
- tiffanyh 5y agoIt was believed that lighttpd leaked memory quite badly, and there was also a period of time where the development/updates on lighttpd dramatically slowed down. Both of which wasn't a concern in the early days of nginx. https://serverfault.com/questions/330413/lighttpds-memory-leaks-a-myth-or-true-if-true-does-it-apply-to-static-conten https://serverfault.com/questions/330413/lighttpds-memory-le...
- NateEag 5y agoMy memory is hazy but I think I remember running into an actual memory leak in lighttpd circa 2008. We were serving dynamic content via FastCGI, IIRC. This was a long time ago and I'm pretty hazy on the details, but I'm pretty sure I remember finding memory leak bug discussions on the lighttpd website around that time, and no clear answers on how to avoid it.
- kijin 5y agoBack in 2008, if you had a FastCGI backend that produced a large body, such as a file download, lighttpd would allocate the same amount of memory and forget to free it afterward. Everything would work fine for a while, but then someone attaches a large file on your busy PHP forum and bam! Your 720MB linode is thrashing like there's no tomorrow. The proper workaround was to send an X-Sendfile header to instruct lighttpd to fetch the file itself, instead of serving the content directly from the backend. It was also more efficient, but it required changes to backend code that made it less portable. I don't know if the bug was ever fixed as lighttpd development had slowed to a crawl and nginx arrived just in time to take away all the market share. The introduction of PHP-FPM around the same time was another factor that favored nginx, because lighttpd typically integrated with PHP using a more fragile setup called fcgi-wrapper. PHP-FPM was much nicer to work with, and nginx could even load-balance across FPM pools. A lot of WordPress sites switched to nginx and never looked back.
- Steltek 5y agoJust to say thank you for this closure ~15 years later. I was on team lighttpd back in the day (I think I liked the config syntax more? I honestly can't remember) but this bug caused a lot of grief and at the time, it appeared like no one knew the cause. Still, lighttpd/fcgi was still better than the epic custom Apache C++ module disaster in the previous iteration.
- fouc 5y agoI remember seeing performance comparisons between lighttpd and nginx back in 2006 or so, and I'm pretty sure nginx was able to handle more requests per second & had lower memory usage. Back then people were getting into using VPS services like linode, and memory usage mattered a lot.
- juangacovas 5y agoLighttpd has received very nice updates lately (HTTP/2, etc.) and I use it daily for mission critical servers (facing private customers) behind HAProxy, Varnish and the like. No problems so far after 5 years.
- synergy20 5y agolighttpd consumes 4MB while nginx is 8MB, so deeply embedded devices lighttpd is still preferred even today.
- e98cuenc 5y agoThe difference is that nginx really works. I had Panoramio, a photo website featured in Google Earth / Maps, using Apache. It started to fail down under load, and I quickly switched to lighttpd. It was faster but crashing, getting OOM, etc. I fixed a memory leak and a few more bugs, but it still crashed every now and then and I looked for alternatives. This was 2006 and nginx was the only realistic alternative on the market. It worked beautifully since day 1. It saved my startup. Next year we got acquired by Google. I only got 1 crash with nginx and it was partially my fault, I had an "expires 30y" on some images, and a morning on feb 2008 I came to the office and the whole site was down. After a very quick gdb session under panic I realized it was trying to get a weekday name on an array with a negative index. Nginx was adding 30 years to the current date and that was over 2038 and it overflowed. Igor fixed that issue in hours, and he graciously explained that I could have used "expires max" Nginx has powered all my startups since then (Freepik, Flaticon, Slidesgo, Besoccer). This guy has added more real value to the economy than most unicorns. A true hero.
- causalmodels 5y agoWait you made Flaticon? I would like to to say thank you. Before I truly got into software I was a humble associate consultant and I honestly don't know how I would have made all those decks without you.
- e98cuenc 5y agoThank you! My partner Alejandro Sánchez is actually who got the idea of Flaticon, and Fernando Fernández did most of the initial implementation. When we hired Fernando he was flipping burgers at BurgerKing :)
- bradknowles 5y agoYears ago, I was working at a small startup here in Austin (named “Ihiji”), and it was my job to completely rebuild their cloud systems infrastructure. They wanted to use lighttpd instead of Apache. It took a while, but with a bit of a kickstart from a friend who worked at Opscode Chef (thanks, Matt Ray!), I was able to get that done. With Apache, at their current max load, the systems would just completely fall over, but with lighttpd, at that same load, the system breathed a little hard. I could push lighttpd 10x more before it fell over. Then we started looking at replacing the haproxy solution, and I looked at nginx. I tried it out. I also tried out replacing lighttpd with nginx. And no matter how hard I pushed nginx, I couldn’t get the damn thing to breathe hard. I couldn’t even push the load average up over 1.0. We went back to lighttpd and haproxy because those tools gave us better monitoring and logging, but we always held nginx in our back pocket in reserve, in case we needed another 10x beyond what lighttpd+haproxy could do. And yes, I did get invited to Edinburgh to do a nice little talk on the subject. They had their ups and downs over the years, but ihiji did end up getting acquired by Control4, and the founders are now off doing other weird and cool things.
- teekert 5y agoI like Traefik, not sure if it "as light", but it works well for me in the personal setting, I use it just by adding some lines to my docker-compose file, no further configuration required. It sits in front of several services and automatically uses Let's Encrypt for certs.