CONCATÉNATION RAPIDE DE CHAINES (SANS API)

cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 - 6 oct. 2006 à 14:26
peug Messages postés 232 Date d'inscription mercredi 25 octobre 2000 Statut Membre Dernière intervention 5 octobre 2012 - 20 déc. 2008 à 16:49
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/39831-concatenation-rapide-de-chaines-sans-api

peug Messages postés 232 Date d'inscription mercredi 25 octobre 2000 Statut Membre Dernière intervention 5 octobre 2012
20 déc. 2008 à 16:49
12/10 +1
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
2 déc. 2007 à 08:58
bonne idée d'ajout
cs_ym_trainz Messages postés 160 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 21 avril 2015
1 déc. 2007 à 17:24
J'ai testé, c'est nickel ! 12/10 ! Lol!
J'ai juste ajouté dans la classe la propriété :

Public Sub Store(ByVal szString As String)
Clear
Append(szString)
End Sub

Merci encore !
Cordialement,
ym_trainz
cs_ym_trainz Messages postés 160 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 21 avril 2015
30 nov. 2007 à 23:15
Voilà qui va me débarrasser de ce fichu fichier tampon ! (j'allais finir par faire des trous sur les pistes du HDD ;-)

C'est vrai que la concaténation naïve genre A=A+B, c'est plus que long.
Le gain de temps est... inestimable !
Merci, cela m'évite de me prendre la tête avec un algo avec des mid$()

Cordialement,
ym_trainz
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
12 juin 2007 à 11:20
C'est vrai, tu as parfaitement raison !
@+
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
12 juin 2007 à 10:08
besoin de ma source dans un projet actuel, pour le boulot (un truc de dingue qui va me faire gagner des heures de boulot)...

je viens de voir ton code, Violent_ken, j'etais passsé a coté de vos commentaires ^^

bah c'est pas mal, dit moi... je pense que le gain de perf se sent... avec un TLB collé au vbp, pour CopyMemory, ca doit bien aller ^^

cela dit, même remarque que j'ai faite à EB, concernant un bout de code qu'il avait soumis en commentaires... le résultat n'est pas le même; tout a fait...
tu conserve la chaine totale en permanence. Ce qui fait que si tu en a plusieurs qui cohabitent, ca prend pas mal de mémoire contigüe...
Ma source prend des bouts de mémoire par ci par là, c'est plus simple à caser en mémoire, et on a moins besoin de réallouer/déplacer le tout en mémoire (juste si le tableau de pointeurs de chaines passe plus ^^

Ensuite, j'ignore si c'est perceptible... je dis juste que le fonctionnement n'est pas identique a 100%
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
13 avril 2007 à 21:18
"Il doublon entre "StrLen + Len(s)" et "(StrLen * 2)" et "LenB(s)"" ==> ok, la taille en octet est le double de la taille de la string...


@+
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
13 avril 2007 à 21:15
"le "do while" ne sert a rien une simple soustraction permet de trouver la taille necessaire." ==> Certes ;)

"Il doublon entre "StrLen + Len(s)" et "(StrLen * 2)" et "LenB(s)"" ==> euh ?

"StrLen 0 dans classinitialize ne sert a rien "> oui d'accord, mais je préfère toujours initialiser mes variables ;)

"CopyMemory ByVal ... ByVal <autant declarer l'api en byval :p"> pas bête...


Ce code n'est pas de moi au départ, mais avec toutes ces remarques cette nouvelle version sera vraiment optimisée !

"bon ça m'ennerve je vais voir si je peux pas coder un truc sympa :p" ==> je l'attend, çà me sera très utile ^^


@+
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
13 avril 2007 à 21:12
StrLen = 0 dans classinitialize ne sert a rien :p

CopyMemory ByVal ... ByVal <== autant declarer l'api en byval :p

bon ça m'ennerve je vais voir si je peux pas coder un truc sympa :p
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
13 avril 2007 à 21:08
le "do while" ne sert a rien une simple soustraction permet de trouver la taille necessaire.

Il doublon entre "StrLen + Len(s)" et "(StrLen * 2)" et "LenB(s)"
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
13 avril 2007 à 21:07
(note : ce code est plus rapide qu'à partir d'un grand nombre de concaténations.)
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
13 avril 2007 à 21:04
Super code, j'en ai eu besoin aujourd'hui ;)

Comme j'avais besoin d'une optimisation maximale pour concatener des millions de strings, et comme j'ai vu "On pourrais surement faire plus rapide en introduisant des APIs", et ben je l'ai fait ;)


Je me suis inspiré d'un bout de code trouvé sur le net que j'ai épuré et légèrement optimisé. L'utilisation est identique à ta source.





Option Explicit

'=======================================================
'CLASSE POUR LA CONCATENATION RAPIDE DE STRINGS
'=======================================================

'=======================================================
'API
'=======================================================
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As _
Any, pSrc As Any, ByVal ByteLen As Long)

'=======================================================
'CONSTANTE
'Private Const BUFFER_SIZE As Long 1000000

Private StrLen As Long
Private Buffer As String


Public Property Get Value() As String: Value = Left$(Buffer, StrLen): End Property
Public Property Let Value(s As String): Buffer vbNullString: StrLen 0: Call Append(s): End Property
Private Sub Class_Initialize(): StrLen = 0: End Sub

'=======================================================
'concatene Value et s
'=======================================================
Public Sub Append(s As String)
Dim l As Long

l = StrLen + Len(s)

Do While l > Len(Buffer)
Buffer = Buffer & Space$(BUFFER_SIZE)
Loop

CopyMemory ByVal StrPtr(Buffer) + (StrLen * 2), ByVal StrPtr(s), LenB(s)

StrLen = l

End Sub





@+
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
9 oct. 2006 à 10:25
Ebarsoft/Renfield les remerciements/message vous concerne tous les 2, mais j'ai écris Renfield et je pensais Ebarsoft, tous les 2 vous êtes des respectables de VB et je vous lève mon chapeau.
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
9 oct. 2006 à 10:21
Oué, super, j'aurais appris des trucs fondamentaux en VB avec toi, si tu fais un tour au cameroun y'aura matière à compensation.
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
9 oct. 2006 à 10:06
Masquées, non....
elles sont simplement visibles plus loin ^^

bien des questions (syntaxe, role...) trouvent leur réponse dans l'explorateur d'objets...
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
9 oct. 2006 à 10:02
Effectivement en ouvrant ta classe avec notepad j'ai pu remarquer à l'interieur de ta propriété Value les lignes:
Attribute Value.VB_UserMemId = 0
Attribute Value.VB_MemberFlags = "200"

Merci Renfield, All in control now, ce sont de petites subtilités très importantes, on peut passer une vie à chercher.
Et pourtant j'ai toujours recommandé aux autres de parcourir les menus d'un logiciel afin de découvrir ses possibilités, ce que je n'applique pas toujours, lol.

De ce fait j'irais également souvent regarder les objets VB à partir de Wordpad, il est probable de voir beaucoup de choses masquées par l'IDE.
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
9 oct. 2006 à 09:49
tu peux t'occuper de tous tes attributs également dans l'explorateur d'objets (F2)

classer par catégories (pour les UserControls)
ajouter un texte descriptif, etc...
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
7 oct. 2006 à 18:54
Asimengo>Non en VB6 il faut le faire en passant par le menu.

1- tu places le caret (curseur texte) dans une ligne de la procedure en question.
2- tu cliques sur menu->outils>attribut de procedure
3- tu cliques sur le bouton "avancées"
4- puis dans la combobox "ID de la procedure" tu choisis "(par defaut)" tu valides et c'est bon

En réalité VB va placer un attribut juste apres la declaration de la procedure dans le fichier source comme ceci :

Public Property Get MaProperty() As Variant
Attribute main.VB_UserMemId = 0

End Property

(Cette ligne est invisible dans l'IDE)

@+
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
7 oct. 2006 à 14:41
Effectivement, les gains de temps sont nettement remarquables lorsqu'il s'agit de concatener plusieurs chaines.

Au fait comment définir une propriété par défaut pour une classe. Est-ce juste par le not reservé "Value" ou autre chose?
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
6 oct. 2006 à 16:29
Ren>Ouai ça ce tient cela va dependre egalement de la façon dont on utilise la classe. Si elle sert uniquement a concatener (ce qui est je pense la principale utilité) c'est plus rapide par contre si on va manipuler la chaine genre X = MaClasse.Value ou X.Append Y.Value la ça devient tout suite autre chose. Et puis evidament cela depend aussi de la configuration de l'ordinateur car au final la chaine unicode crée fera de toute façon la même taille.

@+

Aller je retire mon premier commentaire car il n'est pas suffisament pertinent. Ne donnons pas de mauvais exemple :p
bouv Messages postés 1411 Date d'inscription mercredi 6 août 2003 Statut Membre Dernière intervention 3 mars 2019 1
6 oct. 2006 à 15:51
Fallait y penser. En tout cas cela va m'être utile pour accelerer un convertisseur de fichiers (ASCII) que j'ai fait. J'ai parfois plusieurs milliers de lignes pour lesquels je dois reclasser les infos.
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
6 oct. 2006 à 14:50
je ne t'apprend rien EBArtSoft, sur le fonctionnement de la chose...

néanmoins, je voulais éclaircir un point.
Le résultat n'est pas vraiment le même, coté mémoire :

tu garde en permanence la chaine contigüe en mémoire.
lors d'un Redim Preserve, s'il n'y a pas assez de place a la suite, Windows va allouer ailleurs, un emplacement suffisant, et y transferer ta chaine courante...

dans le code que je propose, les chaines ajoutées sont placées "où il y a de la place"
mais pas de manière (forcément) contigüe...
en cas de redim, seul le tableau qui contient finallement le pointeur vers les chaines est redimensionné et retransféré en mémoire... on y gagne, à ce niveau là.

au final, ton code est plus lent, même en passant par un TLB
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
6 oct. 2006 à 14:43
ah oui, dsl, un oubli, je pensais partir sur autre chose, et j'ai oublié de revenir sur ByRef ^^
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
6 oct. 2006 à 14:29
a oui j'oubliais de preciser que les Chaines ce passe en ByRef evidament ce serait bete de créer des chaines temporaire a tour de bras... pour la rapidité c'est pas cool :p ca pose quelques soucis mineur quand on passe des variant ou des nombres mais la on sort du sujet !

@+