Cela peut sembler une question étrange pour certains d'entre vous.
Je suis un programmeur Java amateur. J'ai développé plusieurs jeux, un programme d'IA qui crée de la musique, un autre programme de peinture et des trucs similaires. C'est pour vous dire que j'ai une expérience en programmation, mais pas en développement professionnel d'applications métiers.
Je vois beaucoup de discussions sur ce site sur les performances. Les gens discutent souvent de ce qui serait l'algorithme le plus efficace en C # pour effectuer une tâche, ou pourquoi Python est lent et Java est plus rapide, etc.
Ce que j'essaie de comprendre, c'est: pourquoi est-ce important?
Il y a des domaines spécifiques de l'informatique où je vois pourquoi les performances sont importantes: les jeux, où des dizaines de milliers de calculs se produisent chaque seconde dans une boucle de mise à jour constante, ou les systèmes de bas niveau sur lesquels d'autres programmes s'appuient, tels que les OS et les VM, etc.
Mais pour l'application commerciale normale de haut niveau, pourquoi les performances sont-elles importantes?
Je peux comprendre pourquoi cela comptait autrefois, il y a des décennies. Les ordinateurs étaient beaucoup plus lents et avaient beaucoup moins de mémoire, il fallait donc bien réfléchir à ces choses.
Mais aujourd'hui, nous avons tellement de mémoire à épargner et les ordinateurs sont si rapides: est-ce vraiment important si un algorithme Java particulier est O (n ^ 2)? Cela fera-t-il réellement une différence pour les utilisateurs finaux de cette application d'entreprise typique?
Lorsque vous appuyez sur un bouton GUI dans une application d'entreprise typique, et en arrière-plan, il appelle un algorithme O (n ^ 2), en ces jours d'informatique moderne - ressentez-vous réellement l'inefficacité?
Ma question est divisée en deux:
- En pratique, aujourd'hui, la performance est-elle importante dans un programme d'entreprise normal?
- Si c'est le cas, donnez-moi des exemples concrets d'endroits dans une telle application, où les performances et les optimisations sont importantes.
la source
Réponses:
Vous avez raison, les performances des applications professionnelles ne sont pas vraiment un sujet important de la manière dont elles sont discutées par la plupart des programmeurs . Habituellement, les discussions liées aux performances que j'entends des programmeurs ont plusieurs problèmes:
Ce sont surtout des optimisations prématurées . Habituellement, quelqu'un veut "le moyen le plus rapide" pour effectuer une opération sans raison apparente, et finit par faire des changements de code qui sont effectués par la plupart des compilateurs de toute façon (comme remplacer la division par la multiplication ou intégrer une méthode), ou passer des jours à faire des changements ce qui aidera à gagner quelques microsecondes à l'exécution.
Ils sont souvent spéculatifs . Je suis heureux de voir que sur Stack Overflow et Programmers.SE, le profilage est fréquemment mentionné lorsque la question est liée aux performances, mais je suis également déçu quand je vois deux programmeurs qui ne savent pas de quel profil discutent les performances. changements connexes qu'ils devraient faire dans leur code. Ils croient que les changements rendront tout plus rapide, mais pratiquement à chaque fois, cela n'aura aucun effet visible ou ralentira les choses, tandis qu'un profileur les aurait dirigés vers une autre partie du code qui peut facilement être optimisée et qui gaspille 80% du temps.
Ils se concentrent uniquement sur les aspects techniques. Les performances des applications orientées utilisateur concernent le sentiment: se sent-il rapide et réactif, ou se sent-il lent et maladroit? Dans ce contexte, les problèmes de performances sont généralement beaucoup mieux résolus par les concepteurs d'expérience utilisateur: une transition animée simple peut souvent faire la différence entre une application qui se sent terriblement lente et l'application qui se sent sensible, alors que les deux passent 600 ms. faire l'opération.
Ils sont basés sur des éléments subjectifs même lorsqu'ils sont liés à des contraintes techniques. S'il ne s'agit pas de se sentir rapide et réactif, il devrait y avoir une exigence non fonctionnelle qui spécifie la vitesse à laquelle une opération doit être effectuée sur des données spécifiques, s'exécutant sur un système spécifique . En réalité, cela se passe plus comme ça: le gestionnaire dit qu'il trouve quelque chose de lent, puis les développeurs doivent comprendre ce que cela signifie. Est-ce lent comme dans "il devrait être inférieur à 30 ms. Alors qu'actuellement, cela gaspille dix secondes", ou lent comme "nous pouvons peut-être réduire la durée de dix à neuf secondes"?
Cela dit, les performances en général sont importantes :
Dans les applications non professionnelles, cela peut devenir crucial. Il y a des logiciels embarqués , des logiciels exécutés sur des serveurs (lorsque vous avez quelques milliers de demandes par seconde, ce qui n'est pas si gros, les performances commencent à être un problème), des logiciels exécutés sur des smartphones , des jeux vidéo , des logiciels pour les professionnels (essayez de gérer un fichier de 50 Go dans Photoshop sur une machine pas très rapide pour s'en convaincre) et même des produits logiciels ordinaires qui sont vendus à beaucoup de monde (si Microsoft Word passe deux fois son temps à faire chaque opération qu'il fait, le temps perdu multiplié par le nombre des utilisateurs deviendra un problème).
Dans les applications d'entreprise, il y a de nombreux cas où une application qui se sent et est ralentiront être haï par les utilisateurs. Vous ne voulez pas cela, ce qui rend vos performances préoccupantes.
la source
a simple animated transition may often be the difference between an app which feels terribly slow and the app which feels responsive
- bien que celles-ci doivent certainement être utilisées avec parcimonie, pour les applications qui jonchent les animations et les transitions partout peuvent être frustrantes si vous regardez ces transitions au quotidien!Oui. Oui. La vitesse d'exécution n'est pas la seule préoccupation que vous devriez avoir, et ce n'est pas aussi pressant qu'en 1982, ou comme c'est toujours le cas sur les systèmes embarqués de faible puissance, mais c'est toujours une préoccupation, et il est important que vous compreniez pourquoi il en est ainsi.
D'une part, la complexité asymptotique que vous mentionnez décrit le comportement d'un programme à mesure que sa taille d'entrée augmente . Un programme non linéaire qui traite de 10 éléments peut vous permettre de faire un travail superflu, mais il vous mordra lorsqu'un jour vous devrez en gérer 1000, car il ne semblera pas seulement plus lent, mais beaucoup, beaucoup plus lent. Et vous ne savez pas (sans analyse approfondie et analyse comparative) si ce point sera à 100 éléments, à 1000 éléments, ou non jusqu'à ce que vous atteigniez 100 000 éléments. Cela peut être difficile à croire, mais le choix du meilleur algorithme est bien sûr beaucoup plus facile que d'estimer ce point pour chaque routine et de choisir votre implémentation en fonction de cette estimation.
Veuillez également lire les bases de l'expérience utilisateur. Il existe des seuils bien documentés qui déterminent comment l'interaction avec un programme est perçue en fonction de ses temps de réponse (10 ms, 100 ms, quelques secondes, etc.). Le franchissement de l'un de ces seuils entraînera le désengagement des utilisateurs de votre application, et à moins que vous ne soyez dans la position heureuse d'écrire un logiciel monopolistique que les gens doivent utiliser, les utilisateurs désengagés se traduisent directement par une valeur commerciale négative car cela entraîne la perte de clients.
Ce ne sont que quelques-unes des raisons pour lesquelles un programmeur professionnel doit connaître la complexité algorithmique et la gérer de manière responsable. De nos jours, il n'est généralement pas nécessaire de sortir de votre chemin et de programmer du code spécialement optimisé et mal lisible pour quoi que ce soit, sauf s'il s'avère que c'est une boucle interne critique, mais vous ne devriez jamais, jamais invoquer une classe de complexité supérieure à ce qui est évidemment nécessaire pour faire le travail.
la source
Oui!
Puisque vous avez demandé des exemples, plusieurs situations quotidiennes viennent à l'esprit:
Gestion des mégadonnées : de nombreuses applications métier sont soutenues par des bases de données et, dans de nombreux cas, ces bases de données débordent de données. Et comme l'espace disque est bon marché, les quantités de données enregistrées et stockées sont folles. Pas plus tard que la semaine dernière, un client s'est plaint que son application était tellement lente, en affichant simplement des nombres moyens (requêtes sur plusieurs millions de lignes ...) heures. L'année dernière, une optimisation algorithmique a réduit le temps de traitement d'un lot de 8 à 4 heures, maintenant il n'entre plus en collision avec le quart de jour!
Réactivité : Il y a eu des études d'utilisabilité (si j'ai le temps, j'ajouterai des liens vers les questions pertinentes sur ux.se ...) que la satisfaction des utilisateurs est fortement liée à la réactivité. Une différence dans un temps de réponse de 200 ms contre 400 ms peut facilement vous coûter un pourcentage important de vos clients vous laissant pour vos concurrents.
Systèmes embarqués : les ordinateurs ne progressent pas plus vite, ils deviennent plus lents et plus petits ^ _ ^ Le développement mobile a un impact énorme sur le développement d'applications. Bien sûr, nous pouvons lancer des cycles de mémoire et de processeur comme Jelly Beans sur des ordinateurs de bureau modernes, mais maintenant votre patron vous demande d'implémenter l'algorithme d'analyse du sommeil sur une montre freakin ou sur une carte SIM ...
la source
Je ne sais pas ce qu'est un programme d'entreprise normal typique. Ce que je sais, c'est que les utilisateurs finissent toujours par alimenter nos programmes avec beaucoup plus de données que ce que nous avions prévu (souvent après leur avoir demandé quelle serait leur taille et ajouté une marge de sécurité) et que dans ce cas, ils s'attendent à une augmentation linéaire de au moment de l'exécution, acceptez un comportement de journalisation et vous plaignez que l'application se bloque en cas de problème. Et ils ont tendance à considérer la taille du résultat plus que la taille de l'entrée sauf dans le cas où il est évident d'après leur PDV que toutes les données d'entrée doivent être traitées.
Alors oui, la performance, au moins au niveau de la complexité, compte. La micro-optimisation à l'intérieur d'une classe de complexité n'a pas vraiment d'importance, sauf si vous êtes visiblement pire que la concurrence (que ce soit dans les benchmarks sur certains marchés ou par perception brute - changer la classe dans la progression "instantané", "pas instantané mais pas l'utilisateur pas passer à autre chose "," assez lentement pour que l’utilisateur passe à autre chose au risque d’interrompre le déroulement des actions "," assez lentement pour que l’utilisateur lance la tâche puis vérifie de temps en temps "," assez lentement que l'utilisateur prévoit de lancer la tâche pendant le déjeuner, la nuit, le week-end ").
la source
Dans les applications professionnelles modernes, les problèmes de performances ne sont pas dus à un manque de CPU ou de mémoire. Mais ils se présentent sous la forme de latences réseau, de performances d'E / S et d'abstractions masquant tout cela. Tout dépend de la qualité du design et de l'expérience des développeurs. Même une simple application CRUD peut s'arrêter si elle tire de la base de données une ligne à la fois au lieu d'exécuter une requête (également connue sous le nom de problème N + 1).
Le problème est qu'avoir une bonne conception et des développeurs expérimentés coûte cher. Et il est généralement beaucoup moins cher d'avoir des utilisateurs irrités que d'investir dans de réelles optimisations de performances. Dans certains cas, les clients auront besoin de hautes performances (par exemple, des navigateurs Web), mais ceux-ci s'appliquent rarement aux applications commerciales courantes.
la source
Gardez à l'esprit que pour les applications basées sur serveur, des centaines, des milliers, voire des millions d'utilisateurs peuvent essayer de faire les choses en même temps. Une petite économie d'efficacité dans une telle situation peut avoir un impact majeur sur la quantité de matériel nécessaire pour répondre aux demandes.
la source
Cela compte certainement beaucoup.
Le problème principal n'est même pas d'être ennuyeux pour l'utilisateur, comme de subir des retards inutiles lorsque les éléments de l'interface graphique sont surchargés deux ou trois fois (ce qui importe sur les graphiques intégrés!) Ou simplement parce que le programme prend tellement de temps à faire ... quoi que ce soit fait (surtout des choses inintéressantes). Bien sûr, c'est aussi un problème.
Il existe trois idées fausses importantes:
Ma femme travaille à l'extrémité supérieure d'un tel "environnement commercial typique". L'ordinateur qu'elle utilise coûte environ 3,5 heures de son temps de travail. Le démarrage de Microsoft Outlook prend - par une bonne journée - environ 3 minutes jusqu'à ce qu'il soit prêt (6-8 minutes en fin de trimestre lorsque les serveurs sont sous forte charge). Certaines de ces feuilles de calcul de 30 000 lignes mentionnées prennent 2-3 secondes pour mettre à jour une valeur pendant laquelle l'ordinateur est "gelé" (sans parler du temps qu'il faut à Excel pour démarrer et les ouvrir en premier!). C'est encore pire lors du partage de bureau. Ne me lancez même pas sur SAP.
Il importe certainement que cent mille personnes perdent chacune 20 à 25 minutes par jour ouvrable sans rien attendre. Ce sont des millions perdusque vous pourriez, au lieu de les perdre, verser des dividendes (ou payer des salaires plus élevés).
Bien sûr, la plupart des employés se situent dans la partie inférieure de l'échelle salariale, mais même dans la limite inférieure, c'est de l'argent .
la source
Vous semblez sous-estimer la vitesse de croissance de N ^ 2. Disons que nous avons un ordinateur et que notre algorithme N ^ 2 prend 10 secondes lorsque N = 10. Le temps passe, nous avons maintenant un nouveau processeur 6 fois plus rapide que notre original, donc notre calcul de 10 secondes est maintenant inférieur à deux secondes. Jusqu'à quel point N peut-il être plus grand et peut-il toujours tenir dans ce temps d'exécution initial de 10 secondes? Nous pouvons désormais gérer 24 articles, soit un peu plus du double. Dans quelle mesure notre système devrait-il être plus rapide pour gérer 10 fois plus d'articles? Eh bien, cela devrait être 100 fois plus rapide. Les données se développent assez rapidement et annulent la progression du matériel informatique pour les algorithmes N ^ 2.
la source
Vous ne croiriez pas la quantité de programmes d'entreprise tiers que nous utilisons au travail, et beaucoup d'entre eux sont ridiculement lents à utiliser par rapport à mes normes personnelles. Si les programmes étaient quelque chose que j'utilise à la maison, je les aurais remplacés il y a longtemps par un autre.
Dans certains cas, la différence va directement dans les coûts, car certains programmes affectent directement le nombre de tâches que je peux accomplir au cours d'une journée, et réduisent ainsi ma productivité et le montant des articles facturables. Je dirais donc qu'il est tout aussi important que les programmes d'entreprise soient au moins suffisamment performants pour ne pas être l'élément limitant du revenu.
Un exemple est la gestion des incidents où le travail est mesuré à 15 minutes d'intervalle (service desk). Si le programme est assez lent pour pousser un ticket à prendre plus de 15 minutes (y compris le travail réel), cela ralentira considérablement le processus. Une cause pourrait être un accès lent à la base de données qui "attend un certain temps" chaque fois que l'utilisateur effectue une action (remplir les détails de la résolution, mettre à jour les informations sur le travail ou similaire). Je peux imaginer qu'il y a des cas où des programmes lents peuvent même affecter des choses plus critiques, comme les détails des patients hospitalisés sur les cas d'empoisonnement urgents - peut-être des allergies aux médicaments ou autres?
la source
Bon nombre des autres réponses couvrent le sujet de manière assez approfondie, je m'en remets donc aux raisons et aux justifications. Au lieu de cela, je veux donner un exemple concret pour montrer comment un choix algorithmique peut avoir de réelles implications.
http://windowsitpro.com/windows-xp/svchost-and-windows-update-windows-xp-still-problem
L'article lié décrit un bogue dans l'algorithme pour calculer les mises à jour de Windows XP. Pendant la majeure partie de la vie de Windows XP, l'algorithme de mise à jour a bien fonctionné. L'algorithme calcule si un correctif a été remplacé par un correctif plus récent et n'a donc pas besoin d'être installé. Vers la fin, cependant, la liste des mises à jour remplacées s'est allongée très longtemps *.
L'algorithme de mise à jour était exponentiel, chaque nouvelle mise à jour prenant deux fois plus de temps à calculer que la précédente ( ). Lorsque les listes ont atteint la plage de 40 mises à jour (* longue ), il a fallu jusqu'à 15 minutes, fonctionnant à pleine capacité, pour vérifier les mises à jour. Cela a effectivement bloqué de nombreuses machines XP pendant la mise à jour. Pire encore, lorsque l'on irait installer les mises à jour, l'algorithme s'exécuterait à nouveau , ce qui prend encore 15 minutes. Étant donné que de nombreuses machines avaient des mises à jour automatiques définies, cela pouvait bloquer les machines pendant 15 minutes à chaque démarrage, et potentiellement à nouveau à une certaine périodicité.
O(n) = 2n
Microsoft a utilisé à la fois des hacks à court terme (suppression des éléments de la liste de mise à jour) et des correctifs à long terme pour résoudre ce problème. Cela était important car les dernières versions de Windows utilisaient également le même algorithme et pourraient un jour rencontrer le même problème.
On voit ici que le choix d'un algorithme a eu de réelles implications. Le mauvais algorithme, bien que correct pendant la majeure partie de la durée de vie du produit, peut néanmoins avoir des impacts négatifs sur la route.
la source
Je pense que vous interprétez le nombre de questions posées sur les performances comme une indication que les exigences de performances pour les applications professionnelles sont importantes au lieu de reconnaître que l' amélioration des performances est difficile . Le simple fait de le faire fonctionner peut être accompli par des techniques de force brute, des essais et erreurs ou en copiant et collant un exemple de code.
Tout le monde peut avoir de la chance et continuer à apporter des modifications jusqu'à ce que quelque chose tourne plus vite, mais cela fonctionne rarement. En raison d'un manque d'expérience, les développeurs verront de l'aide extérieure. Dans certains environnements, l'amélioration des performances est un problème unique, donc poser une question spécifique sur un site comme StackOverflow peut être la seule option. De plus, de nombreux consultants gagnent leur argent en étant en mesure d'intervenir et de résoudre ce type de problèmes.
la source
Cela dépend fortement de la façon dont vous définissez les «bonnes performances». Vos algorithmes doivent toujours utiliser la meilleure complexité possible. Abusez les failles pour accélérer votre cage moyenne. Mettre en mémoire tampon et précharger / précompiler autant que possible dans un programme interactif.
Il existe une autre définition de «bonnes performances»: optimiser les constantes de votre classe de complexité. C'est là que C ++ obtient son titre, où les gens commencent à appeler Java slow, où 5% de temps d'exécution en moins semblent être le Saint Graal. En utilisant cette définition, vous avez raison. Le matériel informatique se complique avec le temps, tandis que les compilateurs s'améliorent de plus en plus. À un moment donné, vous ne pouvez pas vraiment optimiser le code bas de gamme mieux que le compilateur - alors laissez-le et concentrez-vous sur vos algorithmes.
À ce stade, l'utilisation de Java / Haskell / C ++ devient juste une autre décision de conception. Le calcul des nombres peut être effectué via OpenCL sur votre GPU. Les interfaces utilisateur ont besoin d'algorithmes à temps constant et elles sont bonnes. La sortie et la modularité sont plus importantes que l'alignement de vos classes pour une utilisation du cache de 20% supérieure. Le multithreading devient important, car les gens ne veulent pas d'une application rapide, ils veulent une application réactive. Ce qui n'est pas important, c'est que votre application soit constamment 10% plus lente qu'elle ne pourrait l'être. Même 50% est bien (mais les gens commencent alors à poser des questions). Concentrez-vous sur l'exactitude, la réactivité et la modularité.
J'adore la programmation en Haskell ou au moins sous une forme fonctionnelle (même en C ++). Être capable d'écrire facilement des tests pour l'ensemble de votre programme est bien plus important que d'être un peu plus rapide dans les travaux par lots.
la source
Assez simple: le coût
Mon ancien employeur avait un système de gestion de l'apprentissage qui était hébergé sur des serveurs physiques en tant que modèle SaaS. Le tas de la machine virtuelle Java a été configuré sur 2 Go pour les machines plus anciennes et 3 Go pour les machines plus récentes et nous avons exécuté plusieurs instances par machine. On pourrait penser que ce serait suffisant.
Avant de commencer, il y avait une équipe de performance chargée de rendre le système réactif et évolutif. Ils ont constaté qu'il y avait certaines données que nous interrogions constamment dans la base de données. Il y avait une table que nous avons même rejoint dans la plupart des requêtes pour récupérer une colonne. Ces données ont rarement changé.
Le problème est que nous avions 2 Go pour travailler. La solution évidente est donc de commencer à mettre en cache toutes les données fréquemment lues. Ensuite, nous avons eu des problèmes de mémoire, commençant juste avant de monter à bord.
Il y avait 2 écoles de pensée à ce sujet:
Le deuxième argument a gagné et j'ai passé plus d'un an à ajuster notre utilisation de la mémoire.
Mon employeur actuel héberge également un système de gestion de l'apprentissage, mais l'héberge un peu différemment. L'évolutivité est si faible qu'une seule installation (répartie sur 4 serveurs virtuels à charge équilibrée) ne peut gérer que 80 clients. Certains de nos plus gros clients obtiennent même leur propre ensemble de serveurs. La plupart des problèmes menant à cela sont des problèmes de performances, comme les requêtes SQL qui monopolisent tous les cycles du processeur, les fuites de mémoire, le code redondant qui fait la même chose plusieurs fois. Nous avons même construit une application interne dont le seul but est de redémarrer les serveurs lorsqu'ils ne fonctionnent pas mal. Il y a un employé qui maintient cet outil (ainsi que d'autres responsabilités).
Ils ont souscrit à la première école de pensée que j'ai mentionnée ci-dessus: jetez plus de matériel parce que les coûts de matériel sont moins chers que les salaires des développeurs.
Cela n'a pas fonctionné aussi économiquement que prévu. Entre le matériel, les licences logicielles et le personnel de support pour gérer les serveurs, nous avons dépensé des millions chaque année pour éviter qu'un développeur ne passe du temps à profiler le code.
Quand j'ai rejoint, j'ai été chargé de résoudre nos problèmes de disponibilité. Étant donné que la plupart de nos problèmes de disponibilité étaient dus à de mauvaises performances, j'ai ajusté les performances de notre code et l'évolutivité est considérablement améliorée, avec une disponibilité bien meilleure. Nous sommes prêts à commencer à augmenter la densité. Inutile de dire que mon salaire est loin d'un million (je le souhaite!), Donc dépenser de l'argent pour me faire régler les performances du code va finir par nous faire économiser des millions par an.
TL; DR
Si vous effectuez une analyse coûts / avantages approfondie, vous constaterez qu'il est moins coûteux de simplement corriger le code. Un problème de performance connu que vous ignorez se transforme en dette technique .
la source
J'ai compris votre question comme ceci: pour obtenir des performances suffisantes (c'est-à-dire que les utilisateurs sont satisfaits et que mon backend ne grince pas), dois-je comprendre la théorie de la complexité algorithmique?
Cela dépend de ce que vous entendez par application métier "typique". Dans de nombreux cas, en particulier de simples systèmes d'information de type CRUD, la réponse serait non. Pour ceux-ci, vous aurez "simplement" (parfois c'est en fait difficile) besoin de pouvoir retracer les goulots d'étranglement des performances: ai-je manqué un index dans ma base de données? Dois-je envoyer trop de données sur le réseau? Ai-je un millier de dollars dans mon front-end angular.js? Il s'agit de construire une architecture saine, de bien connaître votre pile technologique et d'éviter le non-sens. Vous pouvez y parvenir si vous êtes un bon artisan, pas nécessairement un informaticien. Une autre façon de dire que les gars qui ont construit l'optimiseur de requêtes Oracle ont traité les problèmes de complexité algorithmique, il vous suffit d'utiliser correctement ce qu'ils vous ont fourni.
Maintenant, il y a des exceptions. Si nous parlons de Big Data ou de Machine Learning, vous devez savoir ce que vous faites et pas seulement utiliser les algorithmes par défaut à votre disposition. Même sur le front-end, si vous commencez à créer des visualisations de données avancées, certaines d'entre elles peuvent impliquer un coût de complexité non linéaire (par exemple, les graphiques de mise en page forcée).
De nos jours, ces exceptions sont de plus en plus courantes et le marché est assez sec lorsque vous recherchez des personnes capables de les gérer. Donc: oui, vous pouvez réussir sans expérience en informatique, mais vous le serez encore plus avec certains.
la source
Les autres intervenants ont couvert la plupart des points de base, mais pour les tâches qui peuvent être parallélisées, les logiciels inefficaces entraînent une augmentation des coûts matériels sous la forme de plus de serveurs, qui utilisent plus d'énergie et nécessitent plus d'espace et de maintenance.
la source