CGI is _computationally_ slow, but in practice it's faster than it needs to be for most sites. Some examples of CGI-powered sites i'm aware of include:
- https://sqlite.org/wasm (same domain, different sub-site)
- https://fossil-scm.org/forum (same domain, separate sub-site)
- https://fossil.wanderinghorse.net
All CGI, all the time, and _plenty_ performant for the purpose.
But if that process is Python or Java it's going to be tens to hundreds of milliseconds before it's ready to serve the request.
It tested in a loop fork/exec and vfork/exec for a dynamic binary and for a static binary with musl.
On an Intel Core i5 6600k:
regular:
fork 13179 ms / 100000 = 131 µs, 7587 per sec
vfork 14423 ms / 100000 = 144 µs, 6933 per sec
static:
fork 3173 ms / 100000 = 31 µs, 31515 per sec
vfork 3833 ms / 100000 = 38 µs, 26089 per sec
However, perhaps 15+ years ago I converted an application to an Apache module from a cgi-bin binary and the performance benefit was immense in an embedded Linux device. We certainly were not talking even about tens requests per second in the CGI version.
You can share state between processes using temporary files/shared memory. Like CGI itself, it doesn’t scale as well, but it’s not even a blip on resource usage unless you’re dealing with thousands of requests per second.
> In particular, it can maintain a database connection all the time (with a retry logic for the case when it gets disconnected).
You can run a daemon that performs the connection pooling for you, and have each request connect to the daemon instead.
This is true, CGI is sensitive to startup latency. It can be addressed with pre-forking, but doing so bears the consequence of increased memory usage at idle workloads.
> As for the connection pooling daemon, you still need to connect to it. It might be faster than talking to the database directly on a different server, but no new connection still beats new local connection.
It’s a nothingburger. A connection pool’s bottleneck is in the TCP connection to the database. A UNIX socket has orders of magnitude less latency (a couple μs) and supports orders of magnitude more throughput (a few GBs/sec). Compared to spawning new processes running interpreters, it’s noise.
Doesn't necessarily extrapolate back another 20 years, but perhaps sheds some light on how "slow" CGI would've been.
On a related note, "modern" cloud-based application development strategies (like AWS Lambda) seem no faster than CGI. We've come full circle. Though now things are more distributed, of course.
Not so uncommon these days tbh