You wouldn’t find any performance difference. Neither of them are hacks or “wrong” coding method. It’s all how you like it.
You can use signals if you are getting circular imports when overriding save method or when saving from somewhere else.
I follow a pattern where, if the changes belong to same model, override the save method, else if they belong to a different model which isn’t linked to the current model (by one to one or one to many), use signals.
Choosing between overriding the save method or utilizing signals isn’t really a question of performance or best-practice. As the documentation says signals are mainly a great way to keep apps decoupled while stile being able to communicate with each other.
Compared to overriding the save method signals also feels more natural to combine with Celery to off-load certain processing to the background.