One of the primary reasons to use C++ over Blueprints is performance. However, in many cases, Blueprint performance is not a problem in practice. Broadly, the main difference is that executing each individual node in a Blueprint is slower than executing a line of C++ code, but once execution is inside a node, it’s just as fast as if it had been called from C++. For example, if your Blueprint class has a few cheap top-level nodes and then calls an expensive Physics Trace function, converting that class to C++ will not improve performance significantly. But, if your Blueprint class has a lot of tight for loops or lots of nested macros that expand into hundreds of nodes, then you should think about moving that code to C++. One of the most critical performance problems will be Tick functions. Executing a Blueprint tick can be much slower than a native tick, and you should avoid tick entirely for any class that has many instances. Instead, you should use timers or delegates to have your Blueprint class only do work when it needs to.
The best way to find out if your Blueprint classes are causing performance problems is to use the Profiler Tool. To see where performance is going in your project, first create a situation where your Blueprint classes are heavily stressing performance (such as spawning a bunch of enemies), then capture a profile using the Profiler tool. Using the Profiler tool, you can dive into the Game Thread Tick and expand the tree until you find individual Blueprint classes (it may group all instances of the same class together, so keep that in mind). Inside the Blueprint classes, you can see the Blueprint function that is taking time, and expand that. If most of the time is in Self, then you are losing performance due to Blueprint overhead. But, if most of the time is in other native events nested inside the function, then your Blueprint overhead is not a problem.
Blueprint Nativization can be used to mitigate many of these concerns, but it does have some drawbacks. First, it changes your cook workflow which can slow down iteration on cooked games. Also, the runtime logic for nativized Blueprints is different than for normal Blueprints so you may see different bugs or behavior depending on the specifics of your game. Most Blueprint features are fully supported in nativization, but some obscure ones may not be. Finally, the performance improvement will not necessarily be as significant as if you had converted it to C++ yourself. Nativization may not solve all of your performance issues, but it should be investigated as a potential solution to performance issues.