Live data from Hacker News

Websocketd

websocketd.com

181–190 of 233 posts

Re: Websocketd

#181

Earlier quoted context omitted.

AFAIK, those are not 'processes' in terms of operating system processes, but instead some kind of parallel running tasks within the Erlang VM (much closer to threads). Edit: If you think I am wrong, could you please explain what is wrong?

AFAIK there is very little difference between processes and threads in linux (both are instances of task_struct), the variability in implementation details specific makes that use for classification useless, and thus the only possible separation of any use is semantics: the difference between processes and threads is whether they share internal state (generally / by default). Erlang's don't, thus processes. Go's do,…

There is an enormous difference between processes and threads in Linux and it's a fairly simple one - each process is allocated a memory space. All those mappings and page table entries are what makes process spawn expensive.

There is a terminology issue though, you're right, and that comes with using OS terms for userspace scheduling. Go coming up with their own term - goroutines - significantly simplifies the conversations. Gorountines, Erlang processes, green threads and fibers are all fundmentally the same thing - M userspace 'tasks', scheduled on to N operating system threads of execution, likely in one OS process. There are some language details as to how they are presented to the user.

Re: Websocketd

#182
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

I would really like to see a benchmark for: stand alone fork in small statically compiled binary and also every combination of: [[vfork, fork] + exec, posix_spawn] + [small static binary, small dynamic binary]. I understand that for big interpreted languages like Python it's certainly slow, but with advent of Rust I would believe that CGI could make a come back. It's fast enough for many tasks and it gives great isolation. Using separation of concerns by using separate processes gives also ability to easily sandbox whole application even by as crude means as original seccomp.

Re: Websocketd

#183
post #115
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

The myth that fork is expensive is pervasive, and speaking to the ways that it is true†, well: performance is relative. fork() only takes around 8ms on my Linux machine and I can get 100,000 posix_spawn() per second there with 100MB RSS. That's "fast enough" for a large number of applications. †: fork() is a lot slower (over 20x) on Windows

I see this argument all the time but its not the fork() that is the most expensive anymore, its the actual program initialization after the fork(). If your app is non trivial (lets say a websocket based chat server that needs to persist messages to a DB and use pubsub to sync them to other processes) it probably needs a connection to a database, a connection to a cache server like Redis or Memcached, etc, or perhaps a connection to some other backend service. Reinitializing these dependency connections from scratch in a new forked process for every single incoming websocket connection is expensive and slow.

On the other hand a Node.js or Go program can have a preestablished pool of keep alive connections to the backends already ready to go and reuse that connection pool for many hundreds or even thousands of concurrent websocket connections. You can approximate something like this with the fork() model by having a local daemon process that manages the connection pool and have your forked process talk to that local helper daemon when it needs a connection, but you are still going to pay a penalty for that compared with having a fully preestablished connection ready to use right there in the process already

Re: Websocketd

#184

Earlier quoted context omitted.

AFAIK, those are not 'processes' in terms of operating system processes, but instead some kind of parallel running tasks within the Erlang VM (much closer to threads). Edit: If you think I am wrong, could you please explain what is wrong?

Traditionally in Unix and Windows contexts, "processes" means separate memory address spaces and OS-guaranteed isolation, and "threads" mean threads of execution that have shared access to one address space. Erlang processes are threads as seen by the OS, but the Erlang runtime implements process-y restrictions that enforce isolation and forbid shared memory between Erlang processes that do infact exist as threads in…

> Erlang processes are threads as seen by the OS

Not true, Erlang processes are userspace threads, not kernel threads. It's an M:N model -- you can run thousands of Erlang processes on a single OS thread. See:

http://erlang.org/euc/08/euc_smp.pdf

and note that each "scheduler" runs on a single OS thread, whereas many processes can run on each scheduler.

Re: Websocketd

#185

Earlier quoted context omitted.

Yes but the poster, above, is complaining about using CGI with a server. My question is, if you're not using CGI/fastCGI with Apache or nginx for example, what is he suggesting should be used instead?

Using your language of choice: You open a socket on a port, listen for connections, when connection from client arrives read bytes from the socket, parse http request from those bytes, do something that may yield bytes in response, write the response bytes to the socket, close the socket (optional). https://beej.us/guide/bgnet/

I asked about how to do this through apache or nginx. I know how to do it as you suggest.

Re: Websocketd

#186

Earlier quoted context omitted.

This is something that confuses me. Servers offer CGI and fastCGI and if you aren't using those to interface with your own code, how do you do so otherwise? Do some languages have their own deep connections into the server flow that makes them faster? I just don't understand this.

You don't need a server like Apache or Nginx. Your code can just bind to 80/443 directly.

Yes you can but that has nothing to do with what I asked.

Re: Websocketd

#187
post #164

Earlier quoted context omitted.

IOW, opening a socket from the routing HTTP server to an application HTTP server. That’s pretty much how FCGI works.

Yeah, people just seemingly realized that there's nothing special about FastCGI that couldn't be done with plain http. And as a bonus, the app itself can work as a server in the dev env, and testing is simpler. (Only, CGI managed to get headers sorta right by embedding them in protocol vars and not the other way around.)

But I already do this and that doesn't answer the question about the difference between fastCGI and what everyone else seems to be using, but not explaining, is a method of direct integration or ability to talk with the server without CGI/fastCGI.

After doing a little research, it appears this can be done by implementing or writing modules that will talk directly to server internals if I'm understanding this correctly.

Re: Websocketd

#188
post #100

Earlier quoted context omitted.

How do you know that you haven't had any issues?

Usually you notice issues by the server locking up, the clients reporting problems, or messages being missing from the log (which you tend to notice when you search for specific things in the logs).

So how do you know that you're not just getting 80% of "log entry X" just because you get hits for them every now and then?

Re: Websocketd

#189
post #115
post #26

This is the second or third "it's CGI again" thing I've seen in the past year. While these things are cool and definitely have their place, it's still worth noting that process per connection scales fairly poorly, simply because processes and forking are relatively expensive, and therefore it's probably unwise to deploy something like this in production anymore. It is what it is, I suppose.

The myth that fork is expensive is pervasive, and speaking to the ways that it is true†, well: performance is relative. fork() only takes around 8ms on my Linux machine and I can get 100,000 posix_spawn() per second there with 100MB RSS. That's "fast enough" for a large number of applications. †: fork() is a lot slower (over 20x) on Windows

Only 8 ms? That's slower than a ping.

You were right about performance being relative. And of course the trade off between ease of development, use and performance. At the end of the day, practical considerations are going to determine what is "expensive".

Re: Websocketd

#190
post #115

Earlier quoted context omitted.

The myth that fork is expensive is pervasive, and speaking to the ways that it is true†, well: performance is relative. fork() only takes around 8ms on my Linux machine and I can get 100,000 posix_spawn() per second there with 100MB RSS. That's "fast enough" for a large number of applications. †: fork() is a lot slower (over 20x) on Windows

I see this argument all the time but its not the fork() that is the most expensive anymore, its the actual program initialization after the fork(). If your app is non trivial (lets say a websocket based chat server that needs to persist messages to a DB and use pubsub to sync them to other processes) it probably needs a connection to a database, a connection to a cache server like Redis or Memcached, etc, or perhaps…

> If your app is non trivial (lets say a websocket based chat server that needs to persist messages to a DB and use pubsub to sync them to other processes) it probably needs a connection to a database, a connection to a cache server like Redis or Memcached, etc

All things that are already generally connection pooled so this point is moot.

> On the other hand a Node.js or Go program can have a preestablished pool of keep alive connections to the backends already ready to go

Which has nothing remotely to do with why they scale. Also so can the forking process, it can quite easily even have a pool of preforked workers ready to go and handle requests to avoid the cost of the fork.

None of the things you've said have anything to do with why Node and Go are more scalable than a forking server. The issue is ram, not the price of setting up connections; processes are much heavier on ram and limit your number of concurrent clients, Node and Go are event driven single process apps that scale better because they consume less resources, not because of all that other stuff you said.

I don't think you really understand what you're saying or you're comparing apples and oranges and don't know it.

Post reply on HN