clappski

Joined 10 years ago

Karma
443
Submissions
189
Member since
Feb 29
C++ software developer, based in London.

me <at> jakeclapp <dot> com

View on Hacker News

Recent submissions

Comment · 2 months ago
I’ve had more difficulty building http1.1 implementations that broadly work, still a lot of weird stuff like incorrect chucked message parsing you have to handle on the server side. Yeah plain TCP is obviously simpler but you can’t consume a raw socket in a browser, that’s why web sockets win for me - easy to consume over api and browser.
Comment · 2 months ago
You can genuinely implement the protocol with good performance in 150/200 lines, from memory;

1. Read the opcode

2. If PING, send PONG. If binary or text, continue

3. Read the header size

4. Read the payload size (which is a variable-width integer, hence getting the header size first)

5. Unmask the payload

6. If fin in the header is false, add the payload to a buffer. Else, either immediately dispatch (continuation buffer is empty) or buffer and dispatch (continuation buffer isn’t empty)

There are extensions like setting RSV1 to indicate you need to decompress the payload, but that’s the only one I’ve encountered building clients for >20 WebSocket based APIs.

Comment · 2 months ago
In my experience (building things like realtime trade monitoring front ends), client side processing sucks. You have 10 or 20 data sources that need joining up in a client defined set of ways (think viewing X price feed with Y trade feed and some Z meta data feed), all natively sending many updates a second - I’ve tried and failed to build a client side heavy implementation (although that might just be my lack of front end skills!), much better to have some DAG of backend processing units that the front end can consume feeds from and remain really light, just managing subscriptions and rendering the data.
Comment · 2 months ago
The claim I was rebutting was specifically about latency. Of course you can make a mess of it, no different than you can with request/response based protocols.

On the other hand, you are going to struggle to implement bidirectional event based protocols without WebSockets that can be consumed by browser based clients or an application - WebSockets are very useful for that exact case, where you have a mixed client type consuming. It means you don’t need to offer web hooks and rest and some streaming protocol, you just have a WebSocket with some defined JSON message types without the rigmarole of distributing .proto or whatever.

Comment · 2 months ago
Yes, WebSockets are very simple to implement a server or a client for. It’s a small variable size header, 5 or so frame types and a typically constant mask over the contents.
Comment · 2 months ago
> The latency is the same because modern browsers multiplex HTTP requests over a single TCP connection that is left open.

In my experience this isn’t true; firstly you’re relying on an implementation detail of the platform that you’re executing on, of which you have no control over on the client side. Secondly, even if you aren’t opening a new connection per request, you’re still travelling through an entire HTTP stack implementation rather than the incredibly simple WebSocket protocol - effectively a length and a mask to get the contents, rather than some (in http1 land) fuzzy parser.

If you can guarantee you’re hitting http2 or http3 then you might be closer in latency, but due to the complexity of both I would imagine plain http1 negotiated persistent WebSockets provide the best latency.

Comment · 4 months ago
At least in that case you can refactor the stored proc to be more performant without pushing application changes.
Comment · 5 months ago
Not at all, for example at secondary/high school you would address male teachers interchangeable as ‘sir’ and ‘mr. Last name’.
Comment · 9 months ago
The mistake is that you did a system update when you wanted to use the computer. Not implying that system updates should be a dangerous thing to do, but just something learnt from experience - I’ve had similar issues, especially with Nvidea drivers and kernel versions getting updated at the same time. The take away is keep the updates to when you have an hour to debug or get comfortable rolling back updates.
Comment · 10 months ago
I like the priorities.

I think a core thing that's missing is that code that performs well is (IME) also the simplest version of the thing. By that, I mean you'll be;

- Avoiding virtual/dynamic dispatch

- Moving what you can up to compile time

- Setting limits on sizing (e.g. if you know that you only need to handle N requests, you can allocate the right size at start up rather than dynamically sizing)

Realistically for a GC language these points are irrelevant w.r.t. performance, but by following them you'll still end up with a simpler application than one that has no constraints and hides everything behind a runtime-resolved interface.

Comment · 1 year ago
You'd have an error about an incomplete type - see https://godbolt.org/z/G4Gsfn7MT

> a pointer, whose size is always known

Yeah, this is exactly how it works. You work with a pointer that acts like a void* in your code, and the library with the definition is allowed to reach into the fields of that pointer. Normally you'd have a C API like

    struct Op;
    Op* init_op();
    void free_op( Op* );
    void do_something_with_op( Op* );

in the header provided by the library that you compile as part of your code, and the definition/implementation in some .a or .so/.dll that you'll link against.*
Comment · 1 year ago
When we're talking about opaque it's really in relation to an individual translation unit - somewhere in the binary or its linked libraries the definition has to exist for the code that uses the opaque type.
Comment · 3 years ago
Reminds me of the shadow paging used in LMDB, which is effectively the same but at the page level rather than the whole tree and allows each reader their own context to read from, rather than a shared reader context.
Comment · 3 years ago

     f" something { my_dict['key'] } something else "
This works in Python already, allowing for nesting is a big QoL improvement
Comment · 3 years ago
C++ has two types of polymorphism;

- Templates (compile time), which are generic bits of code that are monomorphized over every combination of template parameters that they're used with.

- Virtualization (runtime), classic OO style polymorphism with a VTable (I think this similar to Rust's dyn trait?).

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton