All the answers posted are relevant...
using the millis() technique, you could keep more than one 'prev' value...
Then you can rank the priority of your time critical functions... calling them perhaps every 10ms, while less time sensitive processes could run every 50, or 100ms.. and some low priorities try tasks only every 1000ms or less often.
With this strategy, you can have as many layers of responsiveness - and if your 'fastest' is say every 10ms, you still have the main loop() and interrupts for very fast (microsecond) latency calls.
If you're concerned how long 'slow' functions take to execute, you can use a spare output pin to watch the entry & exit timing with a scope - which can help you determine the minimum call timing that will allow that function to execute and return.