Single shader with many variations - how to optimize?

I have a shader which has a number of compile-time options controlled by 8 different #if / #endif blocks. (Basically these blocks are enabled based on the current biome - so for example, if we’re rendering a terrain patch that is on the border between a “grass” biome and a “sand” biome, then both the ENABLE_GRASS and ENABLE_SAND symbols will be defined.)

I’m trying to decide if I need to memoize the instances of these shaders - in other words, is it OK (from a performance standpoint) to create a new instance of the shader for every terrain patch? This means calling “new TerrainShader” every time a new terrain patch scrolls into view. Alternatively, I can keep a table of terrain shaders already created, and try to re-use an existing shader instance that has the same set of #define symbols.

A “terrain patch” in my framework is a 16 meter x 16 meter section of terrain, consisting of 64 x 64 quads. Generally there are 3-4 terrain patches visible in the scene at any time, but that changes as you move around.

It’s more performant to cache a shader and reuse it whenever possible. Compiling shaders is a very expensive task.