Partage
  • Partager sur Facebook
  • Partager sur Twitter

[C#] Optimisation de code

Sujet résolu
    31 mai 2019 à 15:17:10

    Bonjour à tous et à toutes,

    J'ouvre ce sujet pour avoir votre aide concernant l'optimisation de mon code ci dessous.

    Ma question est simple, qu'est ce que je pourrait changer, améliorer ou simplifier pour gagner en tant d'exécution et réduire la quantité de ressources utilisées ? (Ce code est exécutée un grand nombre de fois, pour l'ajout de mot dans la BDD ou la recherche)

    using System;
    using System.Collections.Generic;
    using System.Text.RegularExpressions;
    using static SearchApp.StringHelpers;
    
    namespace SearchApp
    {
        class Phonex
        {
            public static double Compute(string word)
            {
                // ETAPE 0 - On supprime les caractères spéciaux et on met la chaîne en majuscules
                word = RemoveDiacritics(word);
                word = RemoveNonLetterChar(word);
                word = word.ToUpper();
    
                // ETAPE 1 - remplacer les y par des i
                word = word.Replace('Y', 'I');
    
                // ETAPE 2 - supprimer les h qui ne sont pas précédées de c ou de s ou de p
                word = Regex.Replace(word, @"([^P|C|S])H", "$1");
    
                // ETAPE 3 - remplacement du ph par f
                word = word.Replace("PH", "F");
    
                // ETAPE 4 - remplacer les groupes de lettres suivantes
                word = Regex.Replace(word, @"G(AI?[N|M])", "$1");
    
                // ETAPE 5 - remplacer les occurrences suivantes, si elles sont suivies par une lettre a, e, i, o, ou u
                word = Regex.Replace(word, @"[A|E]I[N|M]([A|E|I|O|U])", "YN$1");
    
                // ETAPE 6 - remplacement de groupes de 3 lettres (sons 'o', 'oua', 'ein') :
                word = word.Replace("EAU", "O");
                word = word.Replace("OUA", "2");
                word = word.Replace("EIN", "4");
                word = word.Replace("AIN", "4");
                word = word.Replace("EIM", "4");
                word = word.Replace("AIM", "4");
    
                // ETAPE 7 - remplacement du son É
                word = word.Replace("É", "Y");
                word = word.Replace("È", "Y");
                word = word.Replace("Ê", "Y");
                word = word.Replace("AI", "Y");
                word = word.Replace("EI", "Y");
                word = word.Replace("ER", "YR");
                word = word.Replace("ESS", "YS");
                word = word.Replace("ET", "YT");
                word = word.Replace("EZ", "YZ");
    
                // ETAPE 8 - remplacer les groupes de 2 lettres suivantes (son ‘an’ et ‘in’), sauf s’il sont suivi par une lettre a, e, i o, u ou un son 1 à 4
                word = Regex.Replace(word, @"AN([^A|E|I|O|U|1|2|3|4])", "1$1");
                word = Regex.Replace(word, @"ON([^A|E|I|O|U|1|2|3|4])", "1$1");
                word = Regex.Replace(word, @"AM([^A|E|I|O|U|1|2|3|4])", "1$1");
                word = Regex.Replace(word, @"EN([^A|E|I|O|U|1|2|3|4])", "1$1");
                word = Regex.Replace(word, @"EM([^A|E|I|O|U|1|2|3|4])", "1$1");
                word = Regex.Replace(word, @"IN([^A|E|I|O|U|1|2|3|4])", "4$1");
    
                // ETAPE 9 - remplacer les s par des z s'ils sont suivi et précédés des lettres a, e, i, o,u ou d'un son 1 à 4
                word = Regex.Replace(word, @"([A|E|I|O|U|Y|1|2|3|4])S([A|E|I|O|U|Y|1|2|3|4])", "$1Z$2");
    
                // ETAPE 10 - remplacer les groupes de 2 lettres suivants
                word = word.Replace("OE", "E");
                word = word.Replace("EU", "E");
                word = word.Replace("AU", "O");
                word = word.Replace("OI", "2");
                word = word.Replace("OY", "2");
                word = word.Replace("OU", "3");
    
                // ETAPE 11 - remplacer les groupes de lettres suivants
                word = word.Replace("CH", "5");
                word = word.Replace("SCH", "5");
                word = word.Replace("SH", "5");
                word = word.Replace("SS", "S");
                word = word.Replace("SC", "S");
    
                // ETAPE 12 - remplacer le c par un s s’il est suivi d’un e ou d’un i
                word = Regex.Replace(word, @"C([E|I])", "S$1");
    
                // ETAPE 13 - remplacer les lettres ou groupe de lettres suivants
                word = word.Replace("C", "K");
                word = word.Replace("Q", "K");
                word = word.Replace("QU", "K");
                word = word.Replace("GU", "K");
                word = word.Replace("GA", "KA");
                word = word.Replace("GO", "KO");
                word = word.Replace("GY", "KY");
    
                // ETAPE 14 - remplacer les lettres suivante
                word = word.Replace("A", "O");
                word = word.Replace("D", "T");
                word = word.Replace("P", "T");
                word = word.Replace("J", "G");
                word = word.Replace("B", "F");
                word = word.Replace("V", "F");
                word = word.Replace("M", "N");
    
                // ETAPE 15 - Supprimer les lettres dupliquées
                word = RemoveDuplicateLetters(word.ToString());
    
                // ETAPE 16 - Supprimer les terminaisons suivantes : t, x
                word = Regex.Replace(word, @"(.*)[T|X]$", "$1");
    
                // ETAPE 17 - Affecter à chaque lettre le code numérique correspondant en partant de la dernière lettre
                Dictionary<string, string> step17 = new Dictionary<string, string>
                {
                    ["1"] = "0",
                    ["2"] = "1",
                    ["3"] = "2",
                    ["4"] = "3",
                    ["5"] = "4",
                    ["E"] = "5",
                    ["F"] = "6",
                    ["G"] = "7",
                    ["H"] = "8",
                    ["I"] = "9",
                    ["K"] = "10",
                    ["L"] = "11",
                    ["N"] = "12",
                    ["O"] = "13",
                    ["R"] = "14",
                    ["S"] = "15",
                    ["T"] = "16",
                    ["U"] = "17",
                    ["W"] = "18",
                    ["X"] = "19",
                    ["Y"] = "20",
                    ["Z"] = "21"
                };
    
                int[] code = new int[word.Length];
                for (int i = word.Length - 1; i >= 0; i--)
                {
                    char c = word[i];
                    var keyValue = step17[c.ToString()];
                    var b = c.ToString();
                    word = word.Replace(b, keyValue);
                    code[i] = int.Parse(keyValue);
                }
    
                // ETAPE 18 - Convertissez les codes numériques ainsi obtenu en un nombre de base 22 exprimé en virgule flottante.
                int puissance = -1;
                double result = 0;
    
                foreach (var a in code)
                {
                    var abc = a * Math.Pow(22, puissance);
                    result += abc;
                    puissance--;
                }
    
                return result;
    
            } // END OF COMPUTE METHOD
        } // END OF CLASS
    }



    D'avance merci ! :D

    • Partager sur Facebook
    • Partager sur Twitter
      4 juin 2019 à 13:24:09

      Petit up, un petit coup d'oeil s'il vous plait :honte:

      • Partager sur Facebook
      • Partager sur Twitter
        4 juin 2019 à 17:16:11

        Hola,

        Je tenterais ceci :

        • Évite les ToString()
        • Remplace ton foreach par un for
        • N'utilise pas Math.Pow --> ( n^-x = (1/n^x))

        je dois louper d'autre choses mais je sais pas si il y a beaucoup à optimiser sur un petit chouïa de code comme ça.
        Y'a peut-être un truc à jouer avec les Regex.Replace... ?

        A toi de faire joujou avec le profiler.

        -
        Edité par LilyKianii 4 juin 2019 à 17:16:42

        • Partager sur Facebook
        • Partager sur Twitter
          4 juin 2019 à 17:44:54

          Merci pour ces pistes, je vais m'y penché :)

          Pour les regex ils faut absolument que ca soit dans l'ordre spécifique et étape par étape, donc je ne suis pas sûr de pouvoir simplifier ça

          • Partager sur Facebook
          • Partager sur Twitter
            4 juin 2019 à 18:04:35

            A mon avis la meilleur solution pour pouvoir faire tourner ce code en masse, c'est de jouer sur le multi-threading
            • Partager sur Facebook
            • Partager sur Twitter
              5 juin 2019 à 7:36:13

              Salut,

              Pour les regex, tu devrais pas avoir besoin du "|" dans les crochets, le comportement par défaut est déjà de considérer une valeur parmi celles là (et le "|" devrait être compris litérallement par le moteur), donc tu pourrais les modifier mais je ne sais pas si ça aura un quelconque impact, au moins ce sera un chouïa plus lisible.

              Tu as peut-être aussi quelques trucs à revoir comme les lignes 82 et 83 : tu ne peux pas avoir "QU" si tu as remplacé tous les "Q".

              EDIT : pareil ligne 87, le premier truc que tu fais est de remplacer les "Y" donc t'auras pas de "GY". Du coup y'en a peut-être d'autres, à regarder.

              -
              Edité par Stormweaker 5 juin 2019 à 7:39:11

              • Partager sur Facebook
              • Partager sur Twitter
                5 juin 2019 à 9:29:49

                Merci pour vos retours !

                Je vais regarder du cotés des regex :) et mettre en place du multi threading

                • Partager sur Facebook
                • Partager sur Twitter
                  5 juin 2019 à 18:42:42

                  Pour commencer, les RegEx et le multi-threading, c'est nimpornawak dans ce cas d'usage.

                  >Ma question est simple, ... gagner en tant d'exécution et réduire la quantité de ressources utilisées ?

                  Elle est peut-être "simple" mais elle surtout très très mal posée.

                  L'optimisation, ça peut être fonction même de la couleur de la diode clignotante sur le rack en face de celui du serveur où tourne votre code super creepy, et super pas élégant (j'en n'ai les yeux qui saignent).

                  Et avant de regarder la couleur de cette foutue diode, il faut (et uil suffit dans 99% des cas) "d'optimiser" la maintenabilité du code.

                  Et là, votre code c'est vraiment une totale plaisanterie.

                  > pour l'ajout de mot dans la BDD ou la recherche

                  Là, cela montre que cela ne sert clairement à rien d'essayer de corriger votre HORRIBLE code.

                  C'est au moteur de base de données de faire cette tambouille, vraisemblable déjà fait via un paramétrage de la "Coalescence" de votre base, si cette tambouille est assez standard.

                  Si c'est pas si standard, je pense que n'importe quel module de recherche "full text" pour base de données est assez flexible pour exprimer de manière bien plus claire cette tambouille.

                  En utilisant les bon outils, la gestion automatique des index et l'optimiseur de plan d’exécution de la base de données exploseront en performance (aussi bien en temps d'exécution, en maintenabilité, scalabilité, etc...) vos bricolages.

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                    6 juin 2019 à 10:15:30

                    Bonjour,

                    Et merci pour ce retour fort sympathique ! :D

                    Ce code est l'application d'un algorithme bien particulier, et par conséquent, ne peut pas être plus "beau". Cela peut paraitre être un bricolage mais derrière cet algorithme ce cache le travail de plusieurs phonéticien, si vous n'avez pas honte de parler ainsi d'un code source d'une personne a la recherche de savoir, ayant au moins honte de critiquer leur travail, car c'est loin d'être un "bricolage" comme vous le pensez si fortement !

                    Ce code n'as pas besoin d’Être "maintenable" car il est fini, de plus, ce traitement coté serveur et plus précisément BDD serait un suicide car beaucoup trop lourd. Il est évident que l'objectif de l'intervention ci dessus n'as pas vraiment pour but d'aider, puisque vous n'avez même pas pris la peine de comprendre et avez tout de suite crier à la mocheté :)

                    Je vous laisse essayé d'implémenter un algorithme de phonex de manière plus propre ;)

                    Merci pour ce moment de rigolade, bonne journée :)

                    EDIT: de plus, non aucun moteur de recherche de BDD permet d'effectuer ce que je fait, je ne vous demande pas de commenter mon projet ou me donner votre avis inutile la dessus, je demande de l'aide pour grapiller du temps de calcul, si vous ne savez pas comment m'aider inutile de cracher votre venin ici :)

                    -
                    Edité par Golden Panda 6 juin 2019 à 10:35:46

                    • Partager sur Facebook
                    • Partager sur Twitter
                      6 juin 2019 à 11:52:30

                      *ups*

                      T'es obligé de faire ça en C# ?

                      La plus grande optimisation serait de le faire à plus bas niveau. C'est pas compliqué comme fonction donc pas besoin de librairie spécifique etc, facilement transposable.

                      EDIT : "Pour les regex ils faut absolument que ca soit dans l'ordre spécifique et étape par étape"

                      Multi thread c'est pas vraiment compatible avec cette contrainte si tu veux opti "CE" code. Sinon de la distribution de calcul avec MapReduce aurait été encore plus performant (suivant les contraintes matérielles / financières). 

                      -
                      Edité par WorstDevEver 6 juin 2019 à 12:21:16

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Try->Fail->Learn->Converge to success :{\displaystyle Q[s,a]:=(1-\alpha )Q[s,a]+\alpha (r+\gamma ~max_{a'}Q[s',a'])}

                        6 juin 2019 à 13:31:09

                        Merci pour ta réponse WorstDevEver

                        J'ai en effet besoin de ce code en C#, je l'ai déja réalisé en python bien plus efficace

                        Multi thread ca n'ira pas en effet, mais j'ai déja fait des optimisations

                        • Partager sur Facebook
                        • Partager sur Twitter
                          6 juin 2019 à 14:21:55

                          On n'a tous commencé par être mauvais, il faut juste en être conscient pour progresser. (Et on sera toujours plus ou moins mauvais)

                          La preuve, j'ai confondu coalescence et collation.

                          > ne peut pas être plus "beau"

                          Clairement, si, cf. les remarques de mes VDD.

                          >cet algorithme ce cache le travail de plusieurs phonéticien

                          C'est pour cela, et pour bien d'autres choses, que les options de collation dans les bases ont été implémentées, ainsi que les outils de recherche "full text" dans les moteurs de ces bases. Ne dénigrez donc pas le travail des implémenteurs de base de données.

                          Pour une présentation des outils de recherche/indexation des outils "full text" de SQL Server :

                          https://docs.microsoft.com/fr-fr/sql/relational-databases/search/full-text-search?view=sql-server-2017

                          Pour de simple "replace" dans la base :

                          https://docs.microsoft.com/fr-fr/sql/t-sql/functions/replace-transact-sql?view=sql-server-2017

                          "replace" + collation :

                          https://database.guide/how-to-replace-all-occurrences-of-a-string-with-another-string-in-sql-server-replace/

                          etc... vous avez évacué les possibilités des bases de données de manière bien péremptoire (et je ne suis pas Perceval, malheureusement ^^).

                          >si vous n'avez pas honte de parler ainsi d'un code source d'une personne a la recherche de savoir

                          Sans coup de pied au cul, on ne progresse pas.

                          Et votre recherche de "savoir", elle s’essouffle rapidement.

                          >ayant au moins honte de critiquer leur travail,

                          Ce n'est pas le leur que je critique, je n'en ai pas les compétences, c'est le vôtre, et j'ai eu l’outrecuidance de penser que mes remarques vous feriez vous rendre compte que vous êtes très très loin de compte de "améliorer ou simplifier pour gagner en tant d'exécution et réduire la quantité de ressources utilisées".

                          >car c'est loin d'être un "bricolage" comme vous le pensez si fortement !

                          Franchement, votre implémentation c'est vraiment, mais alors sans le moindre doute, un bon vieux "bricolage" qui ne fait pas honneur au travail de ces phonéticiens.

                          >Ce code n'as pas besoin d’Être "maintenable" car il est fini.

                          Cela montre votre total amateurisme dans le domaine du développement informatique. Vous ne vous rendez même pas compte de l'énormité de ce type de remarque.

                          >ce traitement coté serveur et plus précisément BDD serait un suicide car beaucoup trop lourd

                          C'est des machines et des softwares qui ont été spécifiquement optimisées pour ce genre de tâche, et se basant sur des décennies d'expériences. Encore une remarque montrant votre amateurisme, encore.

                          >l'intervention ci dessus n'as pas vraiment pour but d'aider

                          Le coup de pied au cul, ça fait avancer, (sauf les ânes).

                          Rangez votre amour propre, écoutez, et faites un argumentaire avec autre chose que des phrases péremptoires basé sur aucune preuves concrètes.

                          Même si vous ne m'écoutez pas, j'espère que votre inconscient vous fera prendre conscience de la faiblesse de votre machin et qu'il remettra en cause votre aplomb des plus mal placé.

                          >puisque vous n'avez même pas pris la peine de comprendre

                          Bien plus que vous n'avez pris la peine de lire mes remarques aux vues de votre argumentaire à l'emporte-pièce.

                          >et avez tout de suite crier à la mocheté

                          Utilisez un simple outil de qualité logicielle sur votre code, n'importe lequel d'un minimum sérieux, et vous verrez que ce jugement n'a rien de subjectif.

                          >Je vous laisse essayé d'implémenter un algorithme de phonex de manière plus propre

                          Bin, simplement en utilisant LINQ correctement pour chainer ET paralléliser vos tambouilles, ça serait bien plus lisible et si votre driver ADO.NET est assez malin, il utilisera automatiquement, de lui-même, les fonctionnalités du serveur de la base de données que je vous ai indiqué pour faire tout ou partie du travail.

                          >de plus, non aucun moteur de recherche de BDD permet d'effectuer ce que je fait

                          Non, mais, vous rigolez !?!?!

                          >je ne vous demande pas de commenter mon projet

                          Je ne commente pas votre projet, je critique votre manière de faire, ça n'a rien à voir.

                          >je demande de l'aide pour grapiller du temps de calcul

                          Bin, juste dans le cas où vous devez le faire 2 fois, la méthode par SGBD vous explose vos "performance" car en stockant la source + un hache de comparaison + plus le résultat, le résultat est obtenu en une complexité de2*O(n). Vous avez calculer la complexité de votre algorithme qui n'est pas parallélisable, lui ?

                          J'enfonce encore le clou sur l'agressivité car vous sembliez être très demandeur de performance, mais si c'était juste pour la rhétorique, je vous laisse à votre bricolage donc la complexité est stratosphérique.

                          Toute mes remarques sont à prendre au sens général, et j'y connais absolument rien en "phonex", mais comme moi, je ne suis pas buté, j'ai demandé à Google "c'est quoi le Phonex Algorithm", et devinez ce qu'il me trouve en7ème résultat (et le premier avec SQL dans le titre ^^):

                          https://sqlpro.developpez.com/cours/soundex/#L7

                          Alors ? Ils sont vraiment très cons les implémenteurs de base de données ? :p

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                            6 juin 2019 à 17:25:34

                            Y a un repo github qui a une implémentation de cet algo en python (et il cite le même cours que bacelar) : https://github.com/lovasoa/phonex/blob/master/phonex/__init__.py

                            • Partager sur Facebook
                            • Partager sur Twitter
                              6 juin 2019 à 18:05:40

                              LOL, il a dû zapper le "chapitre" 7 du cours.
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                7 juin 2019 à 9:19:29

                                Pour ceux qui me propose l'implémentation de cet algo en python, je l'ai déja dit, je n'en ai pas besoin en python

                                Pour ceux qui me propose de passer par la BDD, non plus, car le besoin est ainsi point barre

                                Et comme dit précédemment, je ne suis pas là pour avoir des suggestions quand à la machine qui va exécuter ce code, je suis la pour avoir des retours sur le  code, savoir si certaines choses peuvent être remplacé par des méthodes plus rapides en exécution. Tout les autres commentaires ne m’intéresse pas, et puisque apparemment c'est trop compliqué pour vous de pas faire du HS, je vais juste clore ce sujet et me débrouiller, bonne continuation :)

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  7 juin 2019 à 11:53:23

                                  Utilisez des outils d'analyse de code, mais si vous êtes froissez par nos commentaires, vous allez pleurer en voyant leurs rapports.

                                  Il n'y pas de bonne réponse à "aller le plus vite possible", et encore plus si vous ne voulez pas donner les vraies contraintes.

                                  Parce que,  niveau perf., la BDD va vous défoncez.

                                  Juste pour bien fixer le ridicule de votre implémentation de l'algorithme, ce que les outils d'analyse de code ne peuvent pas deviner, c'est qu'a chaque "replace" vous scannez toute la chaine, donc environ 60 fois, pour un truc en 18 étapes, c'est 3 fois trop minimum.

                                  Et c'est sans compter la fusion d'étapes qui sont facile, comme les étapes 0 et 1.

                                  Et l'utilisation d'une bonne machine à état permettrait de faire les 18 étapes en 1 passe. Ce qui serait bien plus performant si on n'a beaucoup plus de texte long que de textes courts. Mais comme vous ne nous donnez même pas la répartition en longueurs ou en densité de substitution, il est impossible de faire un choix correct d'optimisation.

                                  Si vous voulez juste vous confortez dans votre self-ego, vous vous êtes trompé d'outil, les forums, c'est fait pour progresser (aussi bien pour les demandeurs que ceux qui répondent).

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                                  [C#] Optimisation de code

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown