I totally agree with others in that be careful how you optimize… having said that, there are some low hanging fruit that can be easy wins at the start so you don’t have to worry about it later.
One of these, especially on the UI front, can be text rendering. I’m not sure if anything’s changed since the XNA days, but it used to be that each glyph was effectively a texture render and so if you have a lot of them, it can add up. It’s all from the same texture so batching is usually pretty good, but when drawing UI there’s usually a lot of other stuff you draw also. Plus if the text isn’t changing, there’s really no point in rendering each glyph independently over and over.
You’ve already mentioned a mitigation for this… a RenderTarget2D object. It’s generally a fairly easy win to just cache the text you want to draw to a texture any time you have new text to draw. Then, on successive draws, you render that cached texture.
So while it’s 100% not a good idea to get too crazy on optimizations, there are generally some easy wins you can take if you want to to jump start. It’s probably worth a day of effort if you know what you want to do… but it’s probably not worth more than a couple days unless there’s some significant driver
I’ve used this approach a number of times, but most recently I did a text scaling prototype that included it. It’s just prototype code, but if you want to see an example of cached text rendering, you can find one there.