```
INSTRUCTION_1:
// subroutine 1
ip++;
goto *dispatch_var[*ip];
INSTRUCTION_2:
// subroutine 2
ip++;
goto *dispatch_var[*ip];
```becomes: ```
RECORD_INST_1:
// record logic
INSTRUCTION_1:
// subroutine 1
ip++;
goto *dispatch_var[*ip];
RECORD_INST_2:
// record logic
INSTRUCTION_2:
// subroutine 2
ip++;
goto *dispatch_var[*ip];
```This way you could directly swap `dispatch_var` with an array populated with the `RECORD_INST_*` labels, and remove one step at runtime.
Or maybe this is what you are trying to avoid to reduce the binary size ?
Writing to a ring buffer and processing in batches should be a relatively big W for everything. You could then filter for repeated instructions to compress, which would lend itself to prefetching the next instruction and buffer with hints. Mixed precision record storage might help too, but you're plucking hairs at that point. Making the sampling adaptive based on the hw profiling counters might eliminate some 'useless' work.
The overhead is already so low that it really should not matter, though. Used to spend a lot of time trying to find wins like this but caches have gotten so large it basically doesn't matter. Even in pathologically memory or io bandwidth bound cases I've found it's usually faster to just run 2 or 4 smaller instances over trying to coordinate all of the threads in a single big one.