IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Connexion C / SQL Server - Mysql - Hyperfile


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut Connexion C / SQL Server - Mysql - Hyperfile
    Bonjour à tous,

    J'ai un joli soft en open source que j'aimerais modifier.

    Il fait appel à de nombreux fichiers de "config" qu'il lit via un fscanf en boucle. Au final, le soft prend environ 0.2 seconde en temps d'exécution.

    Après quelques tests d'optimisation (En chargeant un fichier dans un tableau en mémoire par une lecture brute d'un fichier de config), je gagne facilement 50% de performance.

    La prochaine étape, à mon sens, pour optimiser au mieux, serait de stocker ces données dans une DB, de préférence SQL Server, Hyperfile ou Mysql.

    De quelles bibliothèques ai-je besoin pour me connecter à l'une de ces DB (Les infos pour chacune d'entre elle m'intéresse, afin de tester les performances de chacune d'entre elle pour mon application).

    Quelqu'un dispose-t-il de bonne références/exemples? dur de trouver quelque chose de concret sur google.

    Pour info, je développe avec VS 2005, et j'ai SQL Server 2005, Mysql 4.1 et Hyperfile pour windev 14.

    Merci d'avance,

    S.

  2. #2
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    MySQL est par exemple fourni avec une librairie d'interface (API) directement utilisable sous Visual Studio, et il y a pas mal d'exemples dans la doc.
    Pour SQL Server, il faut fouiller MSDN. Hyperfile, je n'ai jamais utilisé.


    Par contre, en hors-sujet : pourquoi optimiser à ce point pour une durée d'exécution initiale aussi faible que 0.2 secondes ? Juste pour t'entrainer, ou tu as un but derrière ?
    Parce que lancer une BD complète pour gagner, au final, très peu de temps par rapport à une lecture en RAM, c'est peut-être disproportionné... Et tu ne gagneras pas forcément autant que tu ne le penses, en plus.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut
    Merci pour la réponse, je vais creuser déjà pour ces deux là. Reste Hyperfile...

    Sinon, pourquoi optimiser à ce point? La réponse est simple, je travaille sur des séquences d'ADN, et l'ensemble du logiciel demande un nombre impressionnant de comparaisons et d'accès à ces valeurs fixes (pour au final calculer des Tm et des dG) qui se chiffrent en dizaine de milliers de comparaisons par run de l'application.

    0.2 * 10000 = 2000 secondes (Temps d'exécution original)
    0.075 * 10000 = 750 secondes (Temps d'exécution après optimisation sans DB)

    Donc tout gain est appréciable dans ce genre d'application et à terme, ça sera un facteur crucial.

    Bonne journée,

    Stephane

  4. #4
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    Au vue des optimisations déjà effectués, je doute que tu gagnes quoique ce soit à utiliser une base de données. Je serais plutôt d'avis que tu nous montres ton code afin de voir ensemble les goulôts d'étranglements de ton programme (processeur, bus, cache, etc).
    "The quieter you become, the more you are able to hear"
    "Plus vous êtes silencieux, plus vous êtes capable d'entendre"

  5. #5
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Mmmm... Tu es ouvert à toutes formes de suggestion côté optimisation, sans toutefois tomber dans le "hack-à-Tonton-Marcel-tout-crade" ?

    Il faudrait savoir combien de données sur disque tu as, quel est leur principe d'organisation et leur taille totale, pour commencer.
    Il faut voir aussi si ton algo est parallélisable, et sur quelle portion minimale des données c'est possible.
    N'oublie pas non plus qu'une BD, c'est complexe, et l'utiliser coûte du temps machine... Il est possible, au vu de tes chiffres, que tu perdes du temps à en utiliser une !!

    Après, tu peux faire des choses comme câbler une BD "SQLite" montée en RAM exclusivement, et/ou pré-charger les données en modifiant leur organisation pour l'adapter à l'algorithme, utiliser tous les cœurs de ton CPU, etc. Parfois, optimiser un algo, c'est jeter l'ancien et repartir suivant un angle totalement différent, il faut en être conscient.

    Une fois l'algo bien optimisé, un coup de profiling dessus (dépendant de la machine d'exécution finale, attention...) afin de traquer les dernier goulets d'étranglement vicieux, et ça devrait être pas mal.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut
    Bonjour,

    Tout d'abord, mettre le code source complet ici, ça serait impensable, c'est très complexe. Par contre, j'ai déjà identifié les goulets d'étranglement au niveau des perfs, et c'est uniquement, dans le programme original, 4 fonctions qui font des fscanf.

    Voici un exemple d'une fonction originale (qui prend à elle seule 0.07 s en moyenne du temps d'exécution) et juste après la version modifiée (qui prend environ 0.04 s) :

    Version originale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    void loadSint4(double sint4Energies[6][6][4][4][4][4], double sint4Enthalpies[7][7][5][5][5][5], int NA, double saltCorrection, double* gArray, size_t gArraySize, double* hArray, size_t hArraySize)
    {
    	int b, c, i1, j1, i2, j2;
     
    	if (NA)
    	{
    		gFile = openFile("sint4.DGD");
    		hFile = openFile("sint4.DHD");
    	}
    	else
    	{
    		gFile = openFile("sint4.DG");
    		hFile = openFile("sint4.DH");
    	}
     
    	for (b = 0; b < 7; ++b)
    		for (c = 0; c < 7; ++c)
    			for (i1 = 0; i1 < 5; ++i1)
    				for (j1 = 0; j1 < 5; ++j1)
    					for (i2 = 0; i2 < 5; ++i2)
    						for (j2 = 0; j2 < 5; ++j2)
    							if (b == 6 || c == 6)
    							{
    								sint4Enthalpies[b][c][i1][j1][i2][j2] = INFINITY;
    							}
    							else if (i1 == 4 || j1 == 4 || i2 == 4 || j2 == 4)
    							{
    								sint4Enthalpies[b][c][i1][j1][i2][j2] = 0;
    							}
    							else
    							{
    								fscanf(gFile, "%lf", &sint4Energies[b][c][i1][j1][i2][j2]);
    								sint4Energies[b][c][i1][j1][i2][j2] += 3.0 * saltCorrection;
    								fscanf(hFile, "%lf", &sint4Enthalpies[b][c][i1][j1][i2][j2]);
    								l++;
    							}
    	fclose(gFile);
    	fclose(hFile);
    }
    Version modifiée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    void loadSint4(double sint4Energies[6][6][4][4][4][4], double sint4Enthalpies[7][7][5][5][5][5], int NA, double saltCorrection, double* gArray, size_t gArraySize, double* hArray, size_t hArraySize)
    {
    	int b, c, i1, j1, i2, j2, l = 0;
     
    	for (b = 0; b < 7; ++b)
    		for (c = 0; c < 7; ++c)
    			for (i1 = 0; i1 < 5; ++i1)
    				for (j1 = 0; j1 < 5; ++j1)
    					for (i2 = 0; i2 < 5; ++i2)
    						for (j2 = 0; j2 < 5; ++j2)
    							if (b == 6 || c == 6)
    							{
    								sint4Enthalpies[b][c][i1][j1][i2][j2] = INFINITY;
    							}
    							else if (i1 == 4 || j1 == 4 || i2 == 4 || j2 == 4)
    							{
    								sint4Enthalpies[b][c][i1][j1][i2][j2] = 0;
    							}
    							else
    							{
    								sint4Energies[b][c][i1][j1][i2][j2] = gArray[l];
    								sint4Energies[b][c][i1][j1][i2][j2] += 3.0 * saltCorrection;
    								sint4Enthalpies[b][c][i1][j1][i2][j2] = hArray[l];
    								l++;
    							}
    }
    Et voici la fonction générique de lecture du fichier/parsing et mise en mémoire dans un tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    size_t loadSettings(int NA, char* filename, double* dataArray)
    {
    	int arraySize = 0;
    	char finalFilename[255] = "";
    	int gCurrentMaxSize = 20;
    	char *buffer = NULL;
    	FILE *pInFile = NULL;
    	char **tab;
    	size_t str_length = 0;
    	int i, j, k;
     
    	strcat(finalFilename, filename);
    	if (NA)
    	{
    		strcat(finalFilename, "D");
    	}
     
    	i = 0;
    	k = 0;
    	pInFile = openFile(finalFilename);
    	while(!feof(pInFile))
    	{
    		buffer = (char*)malloc(150);
    		fgets(buffer, 150, pInFile);
    		tab = split(buffer, "\t", 0);
    		for (j = 0;tab[j];j++)
    		{
    			if (((k + 1) * sizeof(double)) > (gCurrentMaxSize * sizeof(double)))
    			{
    				gCurrentMaxSize += 50;
    				dataArray = (double *)realloc (dataArray, gCurrentMaxSize * sizeof(double)); 
    			}
    			dataArray[k] = atof(tab[j]);
    			k++;
    		}
    		free(tab);
    		i++;
    	}
    	if (k > 0) arraySize = k - 1;
    	free(buffer);
    	return arraySize;
    }
    Il faut savoir que dans la version modifiée, gArray et hArray sont initialisées dans le main par une fonction générique qui va lire les fichiers (.DG* & .DH*) en bulk et stocke le tout dans un tableau en mémoire. Le gain de performance inclus la génération des deux tableaux.

    Pour info, les fichiers concernés comportent 576 lignes contenant chacune 16 valeurs séparées par un tab, pour un total de 9216 valeurs à lire.

    Le seul endroit qui consomme réellement beaucoup de temps processeur est le fscanf dans la version originale et la lecture du fichier dans la version modifiée.

    Il est peut-être encore possible d'optimiser la fonction de lecture du fichier.

    Il faut aussi savoir que chacune des fonctions qui consomme du temps processeur va lire 2 fichiers (.DG* & .DH*), certains comprennent quelques dizaines ou centaines de valeurs (Dans ce cas, le fscanf ne nuit pas aux perfs) d'autres plusieurs milliers.

    Mon idée était de tester les perfs en chargeant les données non pas des fichiers mais directement à partir d'une DB, en faisant une requête qui retournerait l'équivalent du fichier valeur/ligne par valeur/ligne.

    Si vous avez d'autres suggestions, je suis ouvert à toute proposition.

    Merci de votre temps et de vos conseils.

    Stephane

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut
    Et oui, je préfère éviter toute forme de "hack-à-Tonton-Marcel-tout-crade" parce l'application doit rester 100% fiable & bug free (Le monde idéal, quoi) mais je ne suis pas contre les tester, pour estimer le gain % au risque.

    Sinon, j'avais pensé à SQLite mais j'ai oublié de poser la question pour la connexion C/SQLite...a voir ce que ça peut donner.

    Pour le profiling en C, que conseillez-vous? J'utilise ANTS Performance Profiler en C# mais je n'en ai jamais utilisé en C. (A vrai dire, j'ai fait très peu de C ces dernières années, ça remonte quasi à l'époque où j'étais étudiant, ce qui ne me rajeunit pas... )

  8. #8
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Côté fonction de lecture, à part virer le realloc (ou y mettre une granularité nettement plus élevée que 50 items) et le split (qui coûte une allocation), je ne vois pas trop où optimiser plus.

    Pour remplacer split, l'idéal est "strchr(buffer,'\t')", puis tu poses un '\0' à la valeur de retour de la fonction.
    Dans l'esprit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    		fgets(buffer, 150, pInFile);
    		char* ptr = buffer ;
    		char* next = NULL ;
    		while (ptr) {
    		    next = strchr(buffer,'\t');
    		    if (next)
    		        (next++)* = 0 ;
    		    dataArray[k++] = atof(ptr);
    		    ptr = next ;
    		}
    		i++;
    Côté granularité du realloc, faudrait voir déjà combien de fois (en moyenne) tu passes dans le code. Pour ceci, un compteur global incrémenté à chaque fois, plus un "rapport" indiquant les tailles atteintes par le tableau, pour chaque fichier.
    Si par exemple tu as une taille minimale de 150 items, avec donc trois passages de realloc systématiquement, il est bien sûr intéressant de démarrer à cette valeur de 150.
    Si, ensuite, ça monte à 300, puis 700, puis 1500, alors le "pas" d'incrémentation devrait plutôt être de l'ordre de 300 cases au lieu de 50. Le tout est de minimiser le nombre de "realloc", car cela implique en général une recopie de TOUTES les données déjà présentes dans le tableau... Coûteux, à force !

    Bon, déjà, avec ça, tu devrais gagner un peu de perfs sur la lecture des fichiers... Pas parfait, étant donné que ce n'est fait qu'une seule fois par fichier, mais c'est déjà ça de pris car le gain se fera pour chaque fichier de données tout de même (s'ils sont nombreux, ça va commencer à être visible).


    Côté SQlite, c'est tout simplement une librairie (statique ou dynamique, au choix) avec une API. La librairie est le moteur de BD lui-même, les données sont stockées sur le disque dur : donc, dans ton cas, mettre le fichier en question sur un RAMDisk sinon ce sera perdu d'avance.
    Toutefois, je doute vraiment que tu puisses obtenir de meilleures performances qu'avec des tableaux C comme tu les utilise, sauf au niveau des recherches au sein même des tableaux en fonction d'un critère...

    Profiling : perso, j'utilise celui de Visual Studio.

    Hacks : on peut aller dans cette catégorie, mais je préfère te prévenir que ça vire vite au truc crade, genre insertion de "memset" dans ta boucle de calcul et autres trucs du même genre, avec coupe d'exécution et tout et tout...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut
    Merci pour ta réponse...

    J'ai suivi tes conseils et fait une petite modif. Vu que tous mes fichiers contiennent un nombre fini et fixe de valeurs, j'ai déclaré mes tableaux en dehors de la fonction et je ne fais plus de realloc. Ca demande de connaître la taille de chaque tableau utilisé à l'avance mais vu que c'est mon cas ici, c'est déjà ça de gagné. C'est moins flexible et générique mais vu que les performances primes...

    Je teste déjà avec ça et je te dis quoi...

    Bonne journée,

    Steph

  10. #10
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    De rien. Je te conseille, si possible, de prendre une bonne marge de sécurité sur la taille de tes tableaux, "au cas où".

    Au pire, prévois un code simple de gestion des débordements, le truc primaire genre assertion afin d'éviter quand même d'avoir un traitement pourri MAIS qui ne plante pas violemment (=> ce qui t'induirait en erreur et pourrait provoquer de gros dysfonctionnements SANS donner la moindre alarme).

    Donc, si jamais l'assertion se lève, tu sais que tu dois recompiler le programme, mais au moins, t'es prévenu.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

Discussions similaires

  1. connexion perl sql server sous linux!
    Par boubadi dans le forum SGBD
    Réponses: 2
    Dernier message: 20/11/2007, 16h30
  2. [JDBC]connexion avec sql server
    Par ridondo dans le forum JDBC
    Réponses: 1
    Dernier message: 26/09/2005, 23h37
  3. création d'utilisateur et Connexion sur SQL Server 200
    Par da_latifa dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 24/07/2005, 12h26
  4. Connexion impossible à SQL Server
    Par LaNat dans le forum Bases de données
    Réponses: 3
    Dernier message: 03/05/2005, 14h33
  5. [jdbc] connexion impossible à sql server
    Par hari dans le forum Eclipse Java
    Réponses: 9
    Dernier message: 01/04/2005, 19h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo