Salut,
je suis nouveau sur le forum, je suis etudiant en economie mais je programme a mes heures perdues, j'ai decouvert ocaml grace au site france-ioi qui m'a fournit les bases du langage.
je programme en ocaml parce que c'est un langage qui est repute pour sa simplicite, sa fiabilite et sa rapidite
Mon niveau en programmation est proche du zero et se limite a quelques scripts en bash
j'ai deja parcouru plusieurs sites pour m'affranchir de cette newbietitude mais je ne souheterais pas m'engager dans des solutions trop complexes pour resoudres des problemes simples alors j'ai besoin d'etre aiguiller alors je fais appel a vous pour m'aider.
voici mon probleme
je voudrais creer une fonction qui fasse une recherche dans un fichier texte basique.
Le programme fonctionne parfaitement pour des fichiers de 6000 lignes sans trop de probleme mais quand je le teste sur un fichier de 50 Mo, il met 27 minutes pour totalement lire les donnees.
Je voudrais savoir si le code est "optimal" ou si Ocaml n'aime pas les gros fichiers avec cette methode.
voici le code
voici la logique du code
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 let cat_grep p a motif motif_2 motif_3 motif_4 motif_5 motif_6 c = let ic = open_in a in try while true do let obj=input_line ic in if ( obj <> "" && p = "-a" ) then begin if ( (cherche_string_char motif obj 1 0 0 0 0)> 0 && (cherche_string_char motif_2 obj 1 0 0 0 0)> 0 && (cherche_string_char motif_3 obj 1 0 0 0 0)> 0 && (cherche_string_char motif_4 obj 1 0 0 0 0)> 0 && (cherche_string_char motif_5 obj 1 0 0 0 0)> 0 && (cherche_string_char motif_6 obj 1 0 0 0 0)> 0) then begin c := !c + 1; end; end else if ( obj <> "" && p = "-o" ) then begin if ( (cherche_string_char motif obj 1 0 0 0 0)> 0 || (cherche_string_char motif_2 obj 1 0 0 0 0)> 0 || (cherche_string_char motif_3 obj 1 0 0 0 0)> 0 || (cherche_string_char motif_4 obj 1 0 0 0 0)> 0 || (cherche_string_char motif_5 obj 1 0 0 0 0)> 0 || (cherche_string_char motif_6 obj 1 0 0 0 0)> 0) then begin c := !c + 1; end; end ; done ; with _-> close_in_noerr ic; in
je passe à la fonction le parametre p (-a ou -o), le repertoire (a) suivi des motifs recherches jusqu'a 6 (motif...) et enfin la reference c.
il ouvre un channel sur le fichier
continue la boucle et ferme le channel a toutes les exceptions rencontrees
dans cette boucle si la ligne tiree du fichier est non-"nulle"(c'est a dire <> '\n') et que et que la presence de tout les motifs est simultanee alors la reference est augmentee d'1 unite
ou si la ligne tiree du fichier est non-"nulle" et que et que la presence d' un des motifs est decelee alors la reference est augmente d'1 unite
la fonction cherche_string_char est recursive elle compare caractere par caractere le texte recherche.
la logique est la suivante
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
43
44
45
46
47
48
49
50
51
52
53
54
55 let rec cherche_string_char rmotif rtab v k l m u_2= let motif = (String.lowercase rmotif) in let tab = (String.lowercase rtab) in let w = ref v in (*w le nbre de boucle effectue*) let p = ref k in (*p indique le nbre de char egaux*) let u = ref l in (*u c char observe de motif*) let r = ref m in (*r c char observe de tab*) let d = ref u_2 in (*d le nbre de boucle reussie effectuee*) let fin = (String.length tab) in let fin_2 = (String.length motif) in if ( fin_2 = !u) then begin u := 0 end ; let trouve = motif.[!u] in let trouve_2 = tab.[!r] in if ( trouve = trouve_2) then begin p := !p + 1; if ( !p = fin_2) then begin d := !d + 1; p := 0; u := !u + 1; r := !r + 1; w := !w + 1; end else begin u := !u + 1; r := !r + 1; w := !w + 1; end ; end else begin p := 0; u := 0; r := !r + 1; w := !w + 1; end ; if ( !r < fin) then begin cherche_string_char motif tab !w !p !u !r !d; end else begin !d end ; in
la fonction recursive prend en parametre le motif recherche, la mot dans lequel on souhaite recherche, v donne le nomvre de boucle effectue, k le nombre de fois le motif a ete trouve, l le nombre de caractere semblable, m le nombre de caratere deja lu du texte ou l'on recherche
on transforme tous en minuscule
les reference w,p,u,r,d s'initialise a vec les valeurs entieres v,k,l,m,u_2
on integre la limite du motif et du texte cible
si la fin du motif est atteinte on continue avec le 1er caractere
on choisit un caratere dans le motif et la cible grace au reference
on effectue une comparaison
on cas de reussite
on incremente la reference qui memorise les reussites au niveau des caracteres
si elle est egale au nbre de terme du motif
alors on incremente
on incremente la reference qui comptabilise les boucles reussie
on reset la comptabilisation des caracteres egaux
on incremente la ref qui fait tourner le motif et celle de la cible
on incremente la ref qui comptabilise les boucles effectuees
sinon
on incremente que u r w
si parcontre un des caracteres du motif n'est pas trouve dans la cible alors on increment que les reference qui comptabilise les boucles effectuees et celle qui choisit les caracteres de la cible
on reset les reference qui note la reussite d'une suite de caracteres trouves et celle qui choisit le caractere du motif a comparer
enfin on verifie que le numero du caractere soit infereieur a la teille de la cible pour empecher un out of bounds si c'est inferieur on recommence les nouvelle valeur.
sinon on lache en pature la valeur le nombre de boucles reussies
je n'ai pas utlise agrep car je connaissais pas encore la methode pour utliser le module
j'ai essaye de voir comment d'autres ont fait et dans la documentation du module Agrep, la construction est semblable (testagrep.ml).
J ai teste la fonction en code interprete et en bytes-code.Je travaille sur un ordinateur que les jeunes de moins de 20 ne peuvent pas connaitre (1ghz,~700mo de ram,dd=100Go,debian;Ocaml 3.09.2).
par contre bash le fais en 27 sec sur la meme machine
il y a quelques sujets qui en parlent et qui m'ont beaucoup aides avant que je m'inscrive (lire un fichier, lexing).
je voudrais savoir si la taille du fichier m'oblige a passer par des buffers (chose que je ne maitrise pas) ou si c'est ma fonction qui est trop lourde.
je parle de buffer car en recherchant sur le web j'ai vu qu'il y avait une histoire de taille des buffers (8192) sur ce lien (http://cristal.inria.fr/~remy/poly/s.../vitesse-copie)
et aussi dans le message sur ocamlex
merci pour vos reponses et le temps passe a me lire
Partager