As with most things... it depends; mainly on your expected message throughput, the complexity of your function and your hardware limitations.
Yes, the function node executes its code in a VM which can have an impact on performance, but for most "normal" use cases, that should be negligible.
All in all, those a things you should simply try out and measure the limitations for your use case, and not fall victim to premature optimization.
If function nodes become a bottleneck, there are solutions of course.
- There is the https://flows.nodered.org/node/node-red-contrib-unsafe-function, which doesn't use a VM.
- use native code for your operations
- don't perform CPU-intensive workload inside Node-RED (i.e. NodeJS), but use separate processes
- ...
Also keep in mind, that CPU-intensive workload can block your NodeJS' event loop, which affects everything running in your Node-RED instance.
I think the topic has also been covered here to some extent a while back: Function Node, which code is more efficient?