HN user

max_k

782 karma

C++ hacker

Posts1
Comments49
View on HN

imply that HTTP and FastCGI are interchangeable and they are not.

But they are interchangeable!

FastCGI and HTTP/1.1 are indeed on the same level. Both are transport protocols for HTTP requests.

It would be technically possible to implement FastCGI as alternate transport protocols in browsers and web servers, just like HTTP/2 (SPDY) and HTTP/3 (QUIC) are alternate transport protocols for HTTP requests.

(This is not what the article and my comment are about, as others already pointed out.)

I agree with the article, FastCGI is better than HTTP for these things.

Though I'd like to make another protocol known: Web Application Socket (WAS). I designed it 16 years ago at my dayjob because I thought FastCGI still wasn't good enough.

Instead of packing bulk data inside frames on the main socket, WAS has a control socket plus two pipes (raw request+response body). Both the WAS application and the web server can use splice() to operate on a pipe, for example. No framing needed. Also, requests are cancellable and the three file descriptors can always be recovered.

Over the years, we used WAS for many of our internal applications, and for our web hosting environment, I even wrote a PHP SAPI for WAS. Quite a large number of web sites operate with WAS internally.

It's all open source:

- library: https://github.com/CM4all/libwas - documentation: https://libwas.readthedocs.io/en/latest/ - non-blocking library: https://github.com/CM4all/libcommon/tree/master/src/was/asyn... - our web server: https://github.com/CM4all/beng-proxy - WebDAV: https://github.com/CM4all/davos - PHP fork with WAS SAPI: https://github.com/CM4all/php-src

Oh, there's another stgit user! ^5 Coming from darcs, I couldn't use git until stgit came along, and today, it's one of those few tools I can't imagine working without. Nothing else matches my way of code hacking. So often, I watch people making a big mess with git, and I always recommend stgit to them, so they can post proper and reviewable branches for merging. But in all these years, I could never convince anybody.

Otherwise, the very first commit should be removing all the personally identifiable information and other telemetry sent back to Matt's personal website

This is one of the things I removed in our WordPress fork. I found it horrifying to learn that an open source software does such a user-hostile thing, and wondered why nobody but me objects.

Related: do only what is necessary. This works on so many levels and is my magic trick to make software faster.

It's a pity computers are so fast and have so much memory that people can get away with not caring about minimalism.

Me too! I've been using it for 20 or so years, and it's one of those pieces I didn't know it was still developed or what features were added, because the feature set from 20 years ago is still enough for me. IOW: maybe it doesn't need a maintainer at all.

that's not the point of the article.

Of course not. The post you're replying to explicitly said the discussion was off-topic. That means it's not discussing the point of the article.

In an actual UI, you will have labels or indicators telling you what the toggle means and what the options are

If it only were that way, we wouldn't complain. But it's not.

checkbox without labels is equally bad UX

Of course, I agree. But nobody asked for that.

Your post ignores the things that were said and replies to things that were not said.

I agree with that; animations can be OK, but when I have a configuration setting, I usually disable them because input latency drives me crazy.

My post replied to "checkboxes vs UI toggles", and replying to that aspect was my main point. That's slightly off-topic, of course. It has to do with animations only because checkboxes wouldn't really benefit from animation, whereas toggles are an obscure visual representation for the same control, and adding animation is a feeble attempt to make it somewhat less obscure, even though it doesn't even try to address the main problem: what does toggle "left" and "right" really mean?

I believe checkbox not benefting from animation is a good thing: it's so clear and obvious that you don't need to animate it.

Back in the days, you had a UI toolkit, and everybody would use those native controls; they looked and felt the same in all application, and you had a central place where you could customize the look. Now every application/website has customized controls for everything; everything looks and works differently. (And don't even get me started with websites implementing their own scrollbars with JavaScript. Uh!)

Custom list control: do Home/End buttons work? How to select multiple items, does Shift-Cursorkeys work? Does Ctrl-Click work? Of course not.

Custom text control: does Ctrl-Left/Right for word jumping work? Does Ctrl-Up/Down for paragraph jumping work? Can I select everything with Ctrl-A or does it select the whole website? Can I select everything from cursor until the end with Ctrl-Shift-End work? Does Copy/Paste work at all? (I have never figured out why Copy/Paste in Teams simply doesn't work. Apparently I'm the only one with this problem.)

Custom dropdown control: does Alt-Down work? Can I scroll the list with the usual keys?

If (web) developers would just use standard controls, everything would work the same, and they wouldn't have to reimplement all the basic things from scratch (or not at all). Web devs could write forms that work without megabytes of JavaScript.

Hamburger menus. Those horrible things didn't need to exist even in old times with small monitors and 640x480 (or less) - but now they exist everywhere on my 32" 4K monitor for no reason.

I just don't like the visual polish more than I like the clarity and responsiveness of the old UI elements.

Agree, that sums my opinion well.

And much software doesn't even look like they preferred eye candy over clarity; it rather looks like they forgot about clarity completely.

Me too, agree with you and GP. And I can't keep wondering why this opinion is so unpopular. Today's UIs are bloated with unnecessary animations (which adds latency). But worse than animations is that UIs are horribly inconsistent; took me a while to figure out those toggles should be clicked, not dragged; or: what is even clickable, how do I scroll, ...? I could go on forever, and probably so can you.

Why do only old nerds complain about this, when today's UIs are so "easy" that every toddler can use the smartphone? Are we just living in the past, getting old; are we the problem, why is our opinion unpopular?

The UNIX model won over object approaches.

That's funny interpretation, because what is this mysterious "UNIX model" and what does it have to do with implementation language?

Also, C++ used to be "C with classes", but has outgrown this single-paradigm thing quite quickly. I do a lot of C++, but I rarely use inheritance and virtual methods. These are not the features that make C++ worthwile for me.

The simplicity of flat memory model, [C], a unified file interface

This "unified file interface" is a nice theoretical idea, and it leaks many nice things to the real world, but has nothing to do with the implementation language - quite contrary, it allows many different languages to communicate. Similar with "flat memory model" - you can have either language in segmented memory and flat memory. There used to be "far pointers" in both C and C++, and now they're gone, so what.

If C++ were actually better for engineering large systems, GNU wouldn't have had a chance.

Oh, if only it were that way, if only inferior engineering systems would just lose and disappear. The sad truth is that survival of a language proves little about quality.

If you believe C is better than C++, fine by me, just opinions. You can say "C++ is bad because it's more complex" or "has too many features", I can understand that, or "C++ is confusing because you can overload operators". My features are your bugs, okay. But I can't comprehend your actual arguments because they are orthogonal to the choice of language.

Maybe I could say something good about some aspects of their coding style, but that would only distract from my main point that I find it pointless to imitate a C++ API in C, when that API is modeled carefully to take advantage of C++ features, and you lose all of that in C. (Not only that - their C API is designed in a way that adds overhead even where none would be necessary in C, by allocating all structs on the heap.)

There are lots of plain C container libraries which are probably suited better for C, if you really must use C, or prefer C for whatever reason that escapes my imagination.

The author contacted me via email yesterday (because they saw I'm writing a lot of C++ code on GH) and asked me for a review. This was my somewhat-grumpy somewhat-trollish reply:

Your library demonstrates that C++ is the superior language because it can to template specialization, resulting in better machine code. For example, your std::span implementation needs to store the element size, resulting in a larger structure (24 instead of 16 bytes), more memory memory accesses, costly integer multiplications everywhere.

C++ can omit all this, and can do simple bit shifts instead of multiplications.

There are many more places where you demonstrate C++'s superiority (e.g. it can safely do deep copies with no special code, while your library can't do copies at all, and even if it could, doing so safely/deeply would be extremely cumbersome with C, both for your library code AND for the code calling your library; all a piece of cake in C++).

Oh, and "Implements a dynamic array similar to std::array" .... that's factually wrong. std::array is not a dynamic array. std::vector is. Interestingly, your std::array implementation uses your std::vector, while adding some more runtime overhead. Hey, it's C, it's slower than C++ is what I learn again here!

It's a rather pointless library, unless your point is to demonstrate that C is a bad programming language.

For my argument, MMIX is not an improvement because it's still a low-level assembly language. True, you can simply skip over the MIX/MMIX source code, but that doesn't help me to like TAOCP. For me, (abstract) source code is the primary source of understanding a concept, and English text is just an accompanying explanation, not the other way round.

Your comments put TAOCP in a historical context. Yes, for the time, TAOCP was a huge achievement and it is a magnificient work. History is interesting, but the question here is about today, and I don't think it's the best way to learn the stuff today. (Again, just my opinion, there's no right and no wrong here.)

This is certainly a matter of taste. I saw many prominent people everywhere praising TAOCP, but I was disappointed when I finally read the first three books some 10+ years ago. So much disappointed that I regret taking all the time to read it - not because they're bad books, but because I think that time would have been better spent learning things a different way. What bothered me most is MIX. I think using a very low-level language to teach algorithms is a pretty bad choice. Algorithms are high-level concepts, and using an assembly-like language just distracts from those concepts; it requires you to solve so many micro-problems orthogonal to the real problem, and forces you to repeat yourself over and over. I prefer to implement abstract ideas in abstract code. Using MIX just causes suffering for no point. I learned a lot about math from TAOCP (but I've never needed it for anything).

If you like Lua coroutines and C++20 coroutines, I have written a piece of code that allows to combine both: https://github.com/CM4all/libcommon/blob/master/src/lua/CoAw...

It's used for example by our "myproxy" project: https://github.com/CM4all/myproxy/blob/master/src/Connection... (Ctrl-F Lua::CoAwaitable) - a Lua coroutine is launched from within a C++20 coroutine and the C++20 coroutine awaits the Lua coroutine. Everything integrated in a non-blocking I/O event loop.

That wouldn't solve the hard problems I meant. Rust portability is an easy problem - it's clear how to port Rust to more architectures, just nobody has done it. But doing interop between Rust and C in both directions, with complicated things like RCU in between - that is a hard and complex problem.

to always use smart pointers for reference counting

Agree - and the Linux kernel is extremely fragile because it is full of ad-hoc manual code like that.

Unfortunately, Rust won't be the rescue, because (in the foreseeable future) Rust will only be available in leaf code due to the many hard problems of transitioning from fragile C APIs to something better. Writing drivers in Rust is useful, but limits the scope of how Rust helps.

Many of Rust's advantages at a tiny fraction of the effort could be had easily with a smooth transition path by switching the compiler from C to C++ mode. The fruit hangs so low, it nearly touches the ground, but a silly Linus rejects C++ for the wrong reasons ("to keep the C++ programmers out", wtf).

Every time I work on the Linux kernel source, I'm horrified by how much pain the kernel developers inflict on themselves. Even with C, it would be possible to install a mandatory coding style that is less fragile.

For example, in the aftermath of the Dirty Pipe vulnerability last year, I submitted a patch to make the code less fragile, a coding style that would have prevented the vulnerability: https://lore.kernel.org/lkml/20220225185431.2617232-4-max.ke... - but my patch went nowhere.

Oh, bike helmets. I missed that thread, and I don't want to start yet another endless internet discussion about helmets, but let me point out one thing: the helmet I did wear likely wouldn't have saved my life, had the fork breakage happened one minute later.

... yes, that's what they say about titanium, why I decided to pay the price, but turns out it's not true.

No. I got a full refund, though. Most importantly, I'm so extremely happy I'm still alive, I don't care about anything else.

A year ago, my titanium fork broke (while driving rather slowly on good tarmac, photo here https://twitter.com/dothebart/status/1486765955254530051), and the titanium frame got a few cracks as well. My motto "the last bike I'll ever buy" collided with reality. Fortunately, I got away with just a few scratches - just a minute later, I would have been at 60+ kph downhill. My new bike has a steel frame. I love it, but titanium was more flexible and more comfortable. And of course titanium is nerdier! :-)

do you use exceptions?

Exceptions, sorry.

I learned C++ in the early 90ies, but didn't like it much; I needed to do plain C for a few years at dayjob and several open source projects until I was fed up with manual error handling and go back to C++. At first with a "-fno-exceptions" policy (using something similar to GLib's GError), but gave up my resistance after a few more years, and now I enjoy exceptions very much. It's not perfect, nothing is, but everything else is uglier and so much more cumbersome.

Exceptions seem inappropriate with writing non-blocking/asynchronous code, because where do you throw stuff when the caller is not on the call stack, but instead wants you to invoke a completion callback... but on the other hand, I don't want to implement two different kinds of error reporting - just look at the C++ standard library, which sometimes throws exceptions, sometimes uses std::errc - no, I wanted one single way to wrap error conditions, and I decided that std::exception_ptr is the way to go. All my error callbacks take an std::exception_ptr parameter, which they can then rethrow eventually, or pass on to the next error callback. Yes, I hate std::exception_ptr because it allocates memory on the heap, I despise implicit dynamic allocations, but everything else is uglier and so much more cumbersome. (I repeat myself.)

Error handling is dirty, no matter how you solve it, but C++ exceptions, with all their disadvantages, allow me to just consider the problem solved and go on with writing real code instead of keeping worrying everywhere. It just works.

I know many projects and corporations have a strict "-fno-exceptions" policy and will not change their minds like I did - that's a matter of personal taste.

Would you consider adding a kqueue implementation?

Can't do, I don't have Apple or BSD anywhere. But if code for it were submitted to me, I would gladly merge it (and try to keep the CI happy).

The MPD version of the event loop is portable and runs on macOS/BSD/Windows, but no kqueue, only poll() (and select() on Windows). This old-school API has its scalability problems, of course, but that matters not so much for MPD.

The event loop can already do Coroutines on all supported targets; here's another open source project where I use this library: https://github.com/XCSoar/XCSoar/tree/master/src/event/ - it's a flight computer (yes, for real airplanes) which also runs on Windows and macOS and iOS, and runs libcurl (and other stuff) as coroutine.

If you want to use my library and need help with integrating it or with adding kqueue support, get in touch with me.