Perso j'ai longtemps bossé sur un système en Python dont les perfs étaient critiques, en me disant que j'ai toujours la ressource d'utiliser Cython en cas de soucis.
Au bout d'un an et demie, la codebase titillait les 20k lignes de code avec en tout et pour tout un seul module de 500 lignes en Cython, soit 2.5% du code, mais dont les fonctions étaient appelées plusieurs centaines de millions de fois par seconde (sur tout le système, hein, parce qu'une opération élémentaire en Python se chiffre en μs sur un seul fil d'exécution).
Bien sûr à ce stade il y avait encore de lourds progrès possibles à faire en perfs, mais le système restait parfaitement concurrentiel (les volumes de données traités étaient vendables) et la leçon que j'en ai tiré, personnellement, c'est que changer radicalement de langage ou s'imposer d'énormes contraintes pour "seulement" gagner des perfs n'est pas utile la plupart du temps. Y'en a qui l'ont fait avec succès, bien sûr (je suis tombé recemment sur un billet d'une équipe qui avait troqué Python+tornado contre Go et qui en étaient ravis), mais ça reste des cas particuliers. Mon cas également était particulier d'ailleurs. Le plus gros de mes optimisations consistait à faire attention aux algorithmes que j'utilisais, à utiliser Redis pour créer des IPC faciles et des caches partagés, et à limiter le nombre d'appels systèmes inutiles.
Pour gagner des perfs, la première chose, indispensable, à faire, c'est de profiler le code incriminé et regarder où tu passes le plus de temps et les fonctions que tu appelles le plus souvent. Sans cette connaissance tu ne peux pas déterminer quoi faire, et encore moins savoir si une solution X ou Y va t'aider ou non. Il y a des tonnes de choses possibles en Python, mais comme dans tous les langages, "no silver bullet".
Quant à partir sur un projet en s'infligeant C++ uniquement à cause de présomptions sur les performances et sans reelle contrainte d'infrastructure (style "mon soft doit être rapide ET tourner avec des super perfs sur un raspberry pi"), je trouve ça contre-productif. En optimisation aussi il y a une loi des 80-20 : 80% du temps d'exécution se déroulera dans une zone qui représente 20% du code, le reste n'ayant qu'un impact négligeable sur les performances. Dans ces conditions, autant coder ces 80% de code "neutre" dans un langage malléable comme python pour faciliter les évolutions du code et la réactivité face aux feature requests ou aux rapports de bugs.