After doing some research (Capacity Planning), it appears as if Civi slows down when there are a lot of smart groups or if the smart groups are children of other groups. What should be some good practices to put in place so that the performance/speed of Civi isn't dramatically impacted by a large number of smart groups? Thanks.
Do you have a few smart groups on which many others depend? If so it's worth making sure they're as quick as possible. We have a script that generates the important ones once per hour - but by putting the contacts into regular groups, rather than smart groups. Regular groups are much faster, and that speeds things up a bit.
We've also turned off smart group caching. This very much depends on your use-case. But if you have a lot of intermittently-used smart groups it can be better to generate each one as needed rather than have a cron job regularly slow everything down by generating them all. But obviously ymmv on this.
Have you used Smart Group caches? https://docs.civicrm.org/user/en/latest/organising-your-data/smart-groups/#smart-group-caching