Picalausa François a écrit :Tu as tout à fait raison, je m'est trompé sur ce coup... je pensais au
passage As Long + StrPtr (qui lui peut poser problème)
Sieste trop courte ? fais gaffe, en plus on perd une heure cette nuit.
:-D
Picalausa François a écrit :
Tu as tout à fait raison, je m'est trompé sur ce coup... je pensais au
passage As Long + StrPtr (qui lui peut poser problème)
Sieste trop courte ? fais gaffe, en plus on perd une heure cette nuit.
:-D
Picalausa François a écrit :Tu as tout à fait raison, je m'est trompé sur ce coup... je pensais au
passage As Long + StrPtr (qui lui peut poser problème)
Sieste trop courte ? fais gaffe, en plus on perd une heure cette nuit.
:-D
Hello,
Il y a une technique très efficace qui consiste à mapper un SAFEARRAY
string...
Ceci évite de devoir allouer deux fois la mémoire (donc gain de temps)
devoir recopier la chaine à chaque modification (ou d'effectuer les
modification en double) puisqu'on travaille sur la même zone
Reste à répéter : "Même en VB, je n'ai pas peur des pointeurs!" deux
trois fois... ou pas!
Voici un bout de code illustrant la technique:
Option Explicit
Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17
Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type
Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type
Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)
Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau
Private Function MapSafeArrrayToString(psa As Long, strText As String)
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False
'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))
'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
End If
End If
End If
End If
End Function
Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False
'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))
'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))
'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function
Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function
Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Byte
Dim i As Long
ReDim byBlah(0)
Blah = "Hello World!"
'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print Chr$(byBlah(i))
Next i
UnmapSafeArray
End If
End Sub
--
Picalausa François
"Jean-Marc" a écrit dans le message de
4425260b$0$11427$
> Bonjour chers collègues,
>
> j'ai un besoin précis d'optimisation: Je dois convertir
> une chaine en un table de Bytes.
>
> J'ai écrit cette fonction, qui fonctionne très bien:
>
> ' s : une chaine
> ' szt : la longuue de cette chaine
> ' t() : le tableau de byte à remplir
> Function CvrtStr2ByteArray(ByVal s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> Dim i As Long
> Dim c As String
>
> For i = 1 To szt
> c = Mid$(s, i, 1)
> If LenB(c) = 0 Then
> t(i - 1) = CByte(0)
> Else
> t(i - 1) = CByte(Asc(c))
> End If
> Next i
> CvrtStr2ByteArray = True
> End Function
>
> Connaitriez vous un moyen de faire cela, mais plus rapidement
> que ne le fait cette implémentation naïve.
> J'ai ici un vrai besoin d'optimisation, car cette fonction est
> un facteur limitant dans un de mes programmes (Rabbit)
> Note: la chaine en paramètre peut être très longeur (jusqu'à
> plusieurs centaines de K) et j'appelle parfois cette fonction
> plusieurs milliers de fois consécutivement.
> Si vous aviez un moyen efficace, je suis preneur, sinon je ferais
> une dll en C, mais je voulais éviter cela pour ce projet en
> particulier.
>
> Pour établir une comparaison, j'ai mesuré les performances de
> ma fonction: 10 mesures de 100 appels avec une chaine aléatoire
> de 65535 caractères.
>
> Résultat: 37 millisecondes par appel de fonction.
>
> Si on peut faire en dessous de 10 millisecondes, je prends :-)
> Sinon, je fais une Dll :-(
>
> --
> Jean-marc
> Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
> "There are only 10 kind of people
> those who understand binary and those who don't."
> mailto: remove '_no_spam_' ;
>
Hello,
Il y a une technique très efficace qui consiste à mapper un SAFEARRAY
string...
Ceci évite de devoir allouer deux fois la mémoire (donc gain de temps)
devoir recopier la chaine à chaque modification (ou d'effectuer les
modification en double) puisqu'on travaille sur la même zone
Reste à répéter : "Même en VB, je n'ai pas peur des pointeurs!" deux
trois fois... ou pas!
Voici un bout de code illustrant la technique:
Option Explicit
Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17
Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type
Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type
Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)
Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau
Private Function MapSafeArrrayToString(psa As Long, strText As String)
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False
'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))
'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
End If
End If
End If
End If
End Function
Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False
'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))
'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))
'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function
Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function
Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Byte
Dim i As Long
ReDim byBlah(0)
Blah = "Hello World!"
'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print Chr$(byBlah(i))
Next i
UnmapSafeArray
End If
End Sub
--
Picalausa François
"Jean-Marc" <NO_SPAM_jean_marc_n2@yahoo.fr> a écrit dans le message de
4425260b$0$11427$ba620e4c@news.skynet.be...
> Bonjour chers collègues,
>
> j'ai un besoin précis d'optimisation: Je dois convertir
> une chaine en un table de Bytes.
>
> J'ai écrit cette fonction, qui fonctionne très bien:
>
> ' s : une chaine
> ' szt : la longuue de cette chaine
> ' t() : le tableau de byte à remplir
> Function CvrtStr2ByteArray(ByVal s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> Dim i As Long
> Dim c As String
>
> For i = 1 To szt
> c = Mid$(s, i, 1)
> If LenB(c) = 0 Then
> t(i - 1) = CByte(0)
> Else
> t(i - 1) = CByte(Asc(c))
> End If
> Next i
> CvrtStr2ByteArray = True
> End Function
>
> Connaitriez vous un moyen de faire cela, mais plus rapidement
> que ne le fait cette implémentation naïve.
> J'ai ici un vrai besoin d'optimisation, car cette fonction est
> un facteur limitant dans un de mes programmes (Rabbit)
> Note: la chaine en paramètre peut être très longeur (jusqu'à
> plusieurs centaines de K) et j'appelle parfois cette fonction
> plusieurs milliers de fois consécutivement.
> Si vous aviez un moyen efficace, je suis preneur, sinon je ferais
> une dll en C, mais je voulais éviter cela pour ce projet en
> particulier.
>
> Pour établir une comparaison, j'ai mesuré les performances de
> ma fonction: 10 mesures de 100 appels avec une chaine aléatoire
> de 65535 caractères.
>
> Résultat: 37 millisecondes par appel de fonction.
>
> Si on peut faire en dessous de 10 millisecondes, je prends :-)
> Sinon, je fais une Dll :-(
>
> --
> Jean-marc
> Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
> "There are only 10 kind of people
> those who understand binary and those who don't."
> mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
>
Hello,
Il y a une technique très efficace qui consiste à mapper un SAFEARRAY
string...
Ceci évite de devoir allouer deux fois la mémoire (donc gain de temps)
devoir recopier la chaine à chaque modification (ou d'effectuer les
modification en double) puisqu'on travaille sur la même zone
Reste à répéter : "Même en VB, je n'ai pas peur des pointeurs!" deux
trois fois... ou pas!
Voici un bout de code illustrant la technique:
Option Explicit
Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17
Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type
Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type
Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)
Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau
Private Function MapSafeArrrayToString(psa As Long, strText As String)
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False
'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))
'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
End If
End If
End If
End If
End Function
Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False
'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))
'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))
'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function
Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function
Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Byte
Dim i As Long
ReDim byBlah(0)
Blah = "Hello World!"
'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print Chr$(byBlah(i))
Next i
UnmapSafeArray
End If
End Sub
--
Picalausa François
"Jean-Marc" a écrit dans le message de
4425260b$0$11427$
> Bonjour chers collègues,
>
> j'ai un besoin précis d'optimisation: Je dois convertir
> une chaine en un table de Bytes.
>
> J'ai écrit cette fonction, qui fonctionne très bien:
>
> ' s : une chaine
> ' szt : la longuue de cette chaine
> ' t() : le tableau de byte à remplir
> Function CvrtStr2ByteArray(ByVal s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> Dim i As Long
> Dim c As String
>
> For i = 1 To szt
> c = Mid$(s, i, 1)
> If LenB(c) = 0 Then
> t(i - 1) = CByte(0)
> Else
> t(i - 1) = CByte(Asc(c))
> End If
> Next i
> CvrtStr2ByteArray = True
> End Function
>
> Connaitriez vous un moyen de faire cela, mais plus rapidement
> que ne le fait cette implémentation naïve.
> J'ai ici un vrai besoin d'optimisation, car cette fonction est
> un facteur limitant dans un de mes programmes (Rabbit)
> Note: la chaine en paramètre peut être très longeur (jusqu'à
> plusieurs centaines de K) et j'appelle parfois cette fonction
> plusieurs milliers de fois consécutivement.
> Si vous aviez un moyen efficace, je suis preneur, sinon je ferais
> une dll en C, mais je voulais éviter cela pour ce projet en
> particulier.
>
> Pour établir une comparaison, j'ai mesuré les performances de
> ma fonction: 10 mesures de 100 appels avec une chaine aléatoire
> de 65535 caractères.
>
> Résultat: 37 millisecondes par appel de fonction.
>
> Si on peut faire en dessous de 10 millisecondes, je prends :-)
> Sinon, je fais une Dll :-(
>
> --
> Jean-marc
> Tester mon serveur (VB6) => http://myjmnhome.dyndns.org
> "There are only 10 kind of people
> those who understand binary and those who don't."
> mailto: remove '_no_spam_' ;
>
Bonjour Picalausa François,
Picalausa François a écrit :
> Hello,
>
> Si tu copymemory(strconv("a",vbFromUnicode)), tu auras la
> caractère voulue (ANSI plutôt qu'UNICODE).
> Il ne faut pas oublier que VB stoque en interne les chaines en
> donc la conversion est nécessaire...
>
Cette conversion n'est elle pas implicite, notamment lors de l'appel
API ?
Il me semble que c'est lorsque qu'une API renvoie une chaîne Unicode
qu'il faut faire une conversion explicite.
Il y a peut être aussi la manière de déclarer les paramètres de l'API
qui a son importance :
As Any
ou
As String
Bonjour Picalausa François,
Picalausa François a écrit :
> Hello,
>
> Si tu copymemory(strconv("a",vbFromUnicode)), tu auras la
> caractère voulue (ANSI plutôt qu'UNICODE).
> Il ne faut pas oublier que VB stoque en interne les chaines en
> donc la conversion est nécessaire...
>
Cette conversion n'est elle pas implicite, notamment lors de l'appel
API ?
Il me semble que c'est lorsque qu'une API renvoie une chaîne Unicode
qu'il faut faire une conversion explicite.
Il y a peut être aussi la manière de déclarer les paramètres de l'API
qui a son importance :
As Any
ou
As String
Bonjour Picalausa François,
Picalausa François a écrit :
> Hello,
>
> Si tu copymemory(strconv("a",vbFromUnicode)), tu auras la
> caractère voulue (ANSI plutôt qu'UNICODE).
> Il ne faut pas oublier que VB stoque en interne les chaines en
> donc la conversion est nécessaire...
>
Cette conversion n'est elle pas implicite, notamment lors de l'appel
API ?
Il me semble que c'est lorsque qu'une API renvoie une chaîne Unicode
qu'il faut faire une conversion explicite.
Il y a peut être aussi la manière de déclarer les paramètres de l'API
qui a son importance :
As Any
ou
As String
"Jacques93" a écrit dans le message de news:
> En faisant :
>
> Private Declare Sub CopyMemory Lib "kernel32" Alias
> (Destination As Any, _
> Source As Any, _
> ByVal Length As Long)
>
> Function CvrtStr2ByteArray(ByRef s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> CopyMemory t(0), ByVal s, szt
>
> CvrtStr2ByteArray = True
> End Function
>
Hello,
On peut aussi le faire sans API, puisque VB supporte un cast
Dim byBytes() As Byte
Dim strString As String
strString = "Hello World"
'<mauvaise foi>Note: tu vois qu'il faut un StrConv? Hein
foi> ;-)
'N'empêche que si jamais je choppe celui qui a enlevé une heure
nuit...!
byBytes = StrConv(strString, vbFromUnicode)
Dim i As Long
For i = 0 To UBound(byBytes)
Debug.Print Chr$(byBytes(i));
Next i
Par contre, Jean-Marc, pourrait-on (si tu as le temps de le faire)
bench des différentes méthodes exposées? Je suis sur ce coup ci très
des résultats et de ce qui les départage...
A priori, le StrConv (ou le passage vers une API qui entraine le même
mécanisme) est particulièrement lent. (le mappage d'une safearray sur
string premettant éventuellement de travailler avec des entiers -
des chrw$ et autres fonctions unicode devrait donc être le plus
Bref, curieux je suis...
"Jacques93" <jacques@Nospam> a écrit dans le message de news:
uWOnUjBUGHA.4300@TK2MSFTNGP14.phx.gbl...
> En faisant :
>
> Private Declare Sub CopyMemory Lib "kernel32" Alias
> (Destination As Any, _
> Source As Any, _
> ByVal Length As Long)
>
> Function CvrtStr2ByteArray(ByRef s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> CopyMemory t(0), ByVal s, szt
>
> CvrtStr2ByteArray = True
> End Function
>
Hello,
On peut aussi le faire sans API, puisque VB supporte un cast
Dim byBytes() As Byte
Dim strString As String
strString = "Hello World"
'<mauvaise foi>Note: tu vois qu'il faut un StrConv? Hein
foi> ;-)
'N'empêche que si jamais je choppe celui qui a enlevé une heure
nuit...!
byBytes = StrConv(strString, vbFromUnicode)
Dim i As Long
For i = 0 To UBound(byBytes)
Debug.Print Chr$(byBytes(i));
Next i
Par contre, Jean-Marc, pourrait-on (si tu as le temps de le faire)
bench des différentes méthodes exposées? Je suis sur ce coup ci très
des résultats et de ce qui les départage...
A priori, le StrConv (ou le passage vers une API qui entraine le même
mécanisme) est particulièrement lent. (le mappage d'une safearray sur
string premettant éventuellement de travailler avec des entiers -
des chrw$ et autres fonctions unicode devrait donc être le plus
Bref, curieux je suis...
"Jacques93" a écrit dans le message de news:
> En faisant :
>
> Private Declare Sub CopyMemory Lib "kernel32" Alias
> (Destination As Any, _
> Source As Any, _
> ByVal Length As Long)
>
> Function CvrtStr2ByteArray(ByRef s As String, _
> ByVal szt As Long, _
> ByRef t() As Byte) As Boolean
> CopyMemory t(0), ByVal s, szt
>
> CvrtStr2ByteArray = True
> End Function
>
Hello,
On peut aussi le faire sans API, puisque VB supporte un cast
Dim byBytes() As Byte
Dim strString As String
strString = "Hello World"
'<mauvaise foi>Note: tu vois qu'il faut un StrConv? Hein
foi> ;-)
'N'empêche que si jamais je choppe celui qui a enlevé une heure
nuit...!
byBytes = StrConv(strString, vbFromUnicode)
Dim i As Long
For i = 0 To UBound(byBytes)
Debug.Print Chr$(byBytes(i));
Next i
Par contre, Jean-Marc, pourrait-on (si tu as le temps de le faire)
bench des différentes méthodes exposées? Je suis sur ce coup ci très
des résultats et de ce qui les départage...
A priori, le StrConv (ou le passage vers une API qui entraine le même
mécanisme) est particulièrement lent. (le mappage d'une safearray sur
string premettant éventuellement de travailler avec des entiers -
des chrw$ et autres fonctions unicode devrait donc être le plus
Bref, curieux je suis...
En faisant :
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
Function CvrtStr2ByteArray(ByRef s As String, _
ByVal szt As Long, _
ByRef t() As Byte) As Boolean
CopyMemory t(0), ByVal s, szt
CvrtStr2ByteArray = True
End Function
En faisant :
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
Function CvrtStr2ByteArray(ByRef s As String, _
ByVal szt As Long, _
ByRef t() As Byte) As Boolean
CopyMemory t(0), ByVal s, szt
CvrtStr2ByteArray = True
End Function
En faisant :
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)
Function CvrtStr2ByteArray(ByRef s As String, _
ByVal szt As Long, _
ByRef t() As Byte) As Boolean
CopyMemory t(0), ByVal s, szt
CvrtStr2ByteArray = True
End Function
> "Picalausa François" a écrit dans le message de
news:
> Hello,
>
> Il y a une technique très efficace qui consiste à mapper un
sur ta
> string...
> Ceci évite de devoir allouer deux fois la mémoire (donc gain de
et de
> devoir recopier la chaine à chaque modification (ou d'effectuer les
> modification en double) puisqu'on travaille sur la même zone
mémoire...
> "Picalausa François" <fpicalausa@chez.com> a écrit dans le message de
news:uxeMJjBUGHA.4764@TK2MSFTNGP11.phx.gbl...
> Hello,
>
> Il y a une technique très efficace qui consiste à mapper un
sur ta
> string...
> Ceci évite de devoir allouer deux fois la mémoire (donc gain de
et de
> devoir recopier la chaine à chaque modification (ou d'effectuer les
> modification en double) puisqu'on travaille sur la même zone
mémoire...
> "Picalausa François" a écrit dans le message de
news:
> Hello,
>
> Il y a une technique très efficace qui consiste à mapper un
sur ta
> string...
> Ceci évite de devoir allouer deux fois la mémoire (donc gain de
et de
> devoir recopier la chaine à chaque modification (ou d'effectuer les
> modification en double) puisqu'on travaille sur la même zone
mémoire...
Hello,
Jean-Marc, ayant quelques problèmes avec mon newsreader, je ne vois
message qu'a travers google groups qui ne fonctionne pas pour répondre
cause d'autres problèmes techniques... Donc je répondrai à côté du
Quand tu utilise StrConv, c'est normal que la chaine mappée ne
rien:
Dim Blah As String
'Blah existe
Blah = "Hello World"
MaFonction(StrConv(Blah, ...))
'Ici, la conversion n'existe déjà plus
Par contre,
Blah = StrConv("...", ...)
MaFonction(Blah, ...)
Fonctionne
Pour le banch, voici une méthode entièrement UNICODE donc plus rapide
condition de changement le traitement à postériori pour travailler en
UNICODE):
Option Explicit
Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17
Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type
Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type
Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)
Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau
Private Function MapSafeArrrayToString(psa As Long, strText As String)
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False
'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))
'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
ElseIf (vt = VT_I2) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = Len(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
End If
End If
End If
End If
End Function
Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False
'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))
'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))
'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function
Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function
Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Integer
Dim i As Long
ReDim byBlah(0)
Blah = "Hello World!"
'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print ChrW$(byBlah(i));
Next i
UnmapSafeArray
End If
End Sub
Le problème est donc plus de retirer le temps de conversion pour
appel (faire à l'avance le StrConv, stoquer le résultat et utiliser
StrPtr pour le copymemory) pour effectivement comparer les méthodes et
la conversion en background... enfin, je crois ;-)
--
Picalausa François
Hello,
Jean-Marc, ayant quelques problèmes avec mon newsreader, je ne vois
message qu'a travers google groups qui ne fonctionne pas pour répondre
cause d'autres problèmes techniques... Donc je répondrai à côté du
Quand tu utilise StrConv, c'est normal que la chaine mappée ne
rien:
Dim Blah As String
'Blah existe
Blah = "Hello World"
MaFonction(StrConv(Blah, ...))
'Ici, la conversion n'existe déjà plus
Par contre,
Blah = StrConv("...", ...)
MaFonction(Blah, ...)
Fonctionne
Pour le banch, voici une méthode entièrement UNICODE donc plus rapide
condition de changement le traitement à postériori pour travailler en
UNICODE):
Option Explicit
Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17
Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type
Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type
Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)
Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau
Private Function MapSafeArrrayToString(psa As Long, strText As String)
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False
'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))
'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
ElseIf (vt = VT_I2) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = Len(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
End If
End If
End If
End If
End Function
Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False
'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))
'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))
'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function
Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function
Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Integer
Dim i As Long
ReDim byBlah(0)
Blah = "Hello World!"
'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print ChrW$(byBlah(i));
Next i
UnmapSafeArray
End If
End Sub
Le problème est donc plus de retirer le temps de conversion pour
appel (faire à l'avance le StrConv, stoquer le résultat et utiliser
StrPtr pour le copymemory) pour effectivement comparer les méthodes et
la conversion en background... enfin, je crois ;-)
--
Picalausa François
Hello,
Jean-Marc, ayant quelques problèmes avec mon newsreader, je ne vois
message qu'a travers google groups qui ne fonctionne pas pour répondre
cause d'autres problèmes techniques... Donc je répondrai à côté du
Quand tu utilise StrConv, c'est normal que la chaine mappée ne
rien:
Dim Blah As String
'Blah existe
Blah = "Hello World"
MaFonction(StrConv(Blah, ...))
'Ici, la conversion n'existe déjà plus
Par contre,
Blah = StrConv("...", ...)
MaFonction(Blah, ...)
Fonctionne
Pour le banch, voici une méthode entièrement UNICODE donc plus rapide
condition de changement le traitement à postériori pour travailler en
UNICODE):
Option Explicit
Private Const FADF_HAVEVARTYPE = &H80
Private Const VT_I2 = 2
Private Const VT_UI1 = 17
Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type
Private Type SAFEARRAY
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
End Type
Private Declare Function VarPtrArray _
Lib "msvbvm60.dll" _
Alias "VarPtr" _
( _
Var() As Any _
) _
As Long
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" _
( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)
Private opsa As Long 'pointeur vers la safearray précédente
Private opvdata As Long 'pointeur vers les données précédentes
Private osb As SAFEARRAYBOUND 'bornes précédentes du tableau
Private Function MapSafeArrrayToString(psa As Long, strText As String)
Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
MapSafeArrrayToString = False
'Vérifie la validité des données en entrée
If ((StrPtr(strText) <> 0) And (psa <> 0)) Then
'Vérifie qu'on a bien démappé précédemment
If (opsa = 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal psa, LenB(sa))
'Demande une array typée en 1D non lockée
If ((sa.fFeatures And FADF_HAVEVARTYPE) And (sa.cDims = 1)
(sa.cLocks = 0)) Then
'Demande de plus que cette array soit typée As Byte ou
Integer
CopyMemory vt, ByVal (psa - 4), LenB(vt)
If (vt = VT_UI1) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = LenB(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
ElseIf (vt = VT_I2) Then
'Enregistre les données actuelle du tableau
opsa = psa
opvdata = sa.pvData
Call CopyMemory(osb, ByVal psa + LenB(sa),
'Remap le tableau
sab.cElements = Len(strText)
sab.lLbound = 0
Call CopyMemory(ByVal psa + LenB(sa), sab,
sa.pvData = StrPtr(strText)
Call CopyMemory(ByVal psa, sa, LenB(sa))
MapSafeArrrayToString = True
End If
End If
End If
End If
End Function
Private Function UnmapSafeArray() As Boolean
Dim sa As SAFEARRAY, vt As Long
Dim sab As SAFEARRAYBOUND
UnmapSafeArray = False
'Vérifie la validité des données en entrée
If (opsa <> 0) Then
'déférence le pointer
Call CopyMemory(sa, ByVal opsa, LenB(sa))
'Restaure les données
Call CopyMemory(ByVal opsa + LenB(sa), osb, LenB(osb))
sa.pvData = opvdata
Call CopyMemory(ByVal opsa, sa, LenB(sa))
'Oublie tout de ce qui s'est passé
opsa = 0
opvdata = 0
osb.cElements = 0
osb.lLbound = 0
End If
End Function
Private Function GetPsa(PPSA As Long) As Long
Call CopyMemory(GetPsa, ByVal PPSA, LenB(GetPsa))
End Function
Private Sub Form_Load()
Dim Blah As String
Dim byBlah() As Integer
Dim i As Long
ReDim byBlah(0)
Blah = "Hello World!"
'ATTENTION : jusqu'à UnmapSafeArray, il est préférable que
'Blah ne sorte jamais du scope
If MapSafeArrrayToString(GetPsa(VarPtrArray(byBlah)), Blah) Then
For i = LBound(byBlah) To UBound(byBlah)
Debug.Print ChrW$(byBlah(i));
Next i
UnmapSafeArray
End If
End Sub
Le problème est donc plus de retirer le temps de conversion pour
appel (faire à l'avance le StrConv, stoquer le résultat et utiliser
StrPtr pour le copymemory) pour effectivement comparer les méthodes et
la conversion en background... enfin, je crois ;-)
--
Picalausa François
Bonjour chers collègues,
j'ai un besoin précis d'optimisation: Je dois convertir
une chaine en un table de Bytes.
Bonjour chers collègues,
j'ai un besoin précis d'optimisation: Je dois convertir
une chaine en un table de Bytes.
Bonjour chers collègues,
j'ai un besoin précis d'optimisation: Je dois convertir
une chaine en un table de Bytes.