If you turn off the GC then no memory is collected. In general this is not something people actually do. The only time I've ever even seen it mentioned is in an old blog post by ESR, and between him and me, at least one of us didn't understand what he was saying.
There are popular problem domains where turning off the GC is useful. The best example is Lambda functions/FaaS. Most invocations are short-lived enough that the GC never triggers anyway, but being able to turn it off can help smooth down your P99s where it does trigger, but the world is going to be thrown away in 50 milliseconds anyway. This is a known, not-uncommon performance optimization in other languages on Lambda; but I have less experience using Go on Lambda.
It's not even exclusive to GC'd languages. A toy raytracer I've written in the past got notably faster if I just didn't deallocate anything. Memory management is expensive, and for unix-y software that runs on some input and then quits it can be worth it to just let the OS do the cleanup.
That doesn’t seem like a real thing. Lambda and every other FaaS that I’m aware of will reuse a single instance of the function for multiple invocations. It is not started from scratch with each invocation. Each instance can live for hours, handling a very large number of (sequential) invocations during that time.
If you’re not GCing, you will almost certainly run into OOMs.
If the FaaS can catch the OOM, restart the instance and re-run the request, the visible effect would be somewhat greater latency for that request. If the service is configured to automatically kill and restart instances after some time or some number of requests, it seems like a reasonable tradeoff. Am I missing something?
> If the FaaS can catch the OOM, restart the instance and re-run the request, the visible effect would be somewhat greater latency for that request.
I’m not aware of an FaaS that would hide the OOM… that falls under the “not a real thing” category I mentioned previously. It would just be a failed request, which is a very visible effect.
Would you like to link me to the Lamda docs that say it will automatically retry the request in case of an OOM?
Also consider that code which OOMs will do so unpredictably. It may have completed half of a task, leaving that task in a corrupt state that requires manual intervention from a human to recover from. If everyone wrote fully idempotent code that can somehow skip the already-completed updates and continue where the OOM occurred, this wouldn’t be a problem, but that isn’t what everyone does. This is certainly a large reason why FaaS do not retry requests automatically at all, in most cases.
> If the service is configured to automatically kill and restart instances after some time or some number of requests, it seems like a reasonable tradeoff.
I don’t believe Lambda has any configuration parameters for those things. That’s not how this is meant to work. Lambda will kill the instance when it has been idle for too long, and that’s the primary factor.
You could manually exit the process when your conditions are met, but why? The benefits of turning off the GC are likely to be negligible. This is a lot of complexity for no real gain. It would take some seriously huge gains demonstrated by well-written benchmarks to convince me that any of this is worthwhile for a FaaS function.
Grug would rather fight t-rex.[0]
If you need absolute performance and control over garbage collection, it’s better to just write the lambda in Rust than to try to hack together a solution by turning off the GC and hoping it doesn’t blow up at the wrong moment.
From that link, here are two choice quotes that I think are highly relevant:
> When you invoke a function, two types of error can occur. Invocation errors occur when the invocation request is rejected before your function receives it. Function errors occur when your function's code or runtime returns an error.
> […]
> When you invoke a function directly, you determine the strategy for handling errors related to your function code. Lambda does not automatically retry these types of errors on your behalf. To retry, you can manually re-invoke your function, send the failed event to a queue for debugging, or ignore the error. Your function's code might have run completely, partially, or not at all. If you retry, ensure that your function's code can handle the same event multiple times without causing duplicate transactions or other unwanted side effects.
So, it won’t automatically retry if a function is being directly invoked and OOMs, which I believe was the context of my most recent reply.
There are a few limited scenarios where certain AWS services that are invoking a Lambda asynchronously will decide to retry a couple of times, because it assumes that this type of function will be okay to call multiple times with the same input. Definitely not something worth relying on.
Do not do this in AWS lambda or OpenFaas. Lambda processes are reused in "warm" invocations and are only short lived in cold, infrequent use cases (read: once every > 45 minutes). This is useful when the process dies at the end of every request (in which case you're relying on the OS to do the GC for you).
Also things like compilers...which tend to make lots of garbage but the processes are so short lived who really cares? All the memory is getting released in no more than a few seconds, worst case.
That seems like something that would eventually cause problem once someone just takes the software already designed and paid for and slaps it onto missile with longer range...