Page 1 sur 1
Optimisation...s #3
Publié : jeu. 23/avr./2009 6:26
par Progi1984
Bonjour, je viens pour gagner encore une dizaine de minutes.
Voilà, je fais actuellement ce code
Code : Tout sélectionner
ForEach LL_Lines()
If LL_Lines()\function = LL_DLLFunctions()\FuncName
sASMContent + LL_Lines()\line + #System_EOL
EndIf
Next
Ce code veut dire, je parse toutes les lignes, si elle font partie de la fonction que je veux écrire, je l'ajoute dans le string avant écriture. Mais pour parser toutes les LL_Lines() -180000 items - et l'ajouter dans sASMContent, ca me prend encore 12minutes.
Donc comment pourrais je optimiser ca ?
Publié : jeu. 23/avr./2009 7:52
par brossden
Je pense qu'il y a très certainement moyen d'optimiser mais il faudrait avoir l'ensemble du code pour définir un algo plus performant.
Si tu mets en ligne toutes les données on pourra certainement t'aider mais avec aussi peu de données je ne vois pas comment on peut faire.
Publié : jeu. 23/avr./2009 7:55
par gnozal
Ben, même réponse que pour #1 je dirais.
Si la liste LL_Lines() était triée, la recherche serait beaucoup plus rapide par technique dichotomique.
Si tu ne peux pas la trier (l'ordre des éléments est important ?), tu peux toujours utiliser une copie de la liste triée mise à jour chaque fois que tu ajoutes un élément à la liste originale.
Ou ajouter un champ 'Ordre' dans la structure de la liste LL_Lines(), \Ordre étant incrémenté à chaque ajout d'élément dans la liste. Tu tries la liste sur \function, et tu peux reconstituer l'ordre à la fin en triant sur \Ordre.
Publié : jeu. 23/avr./2009 8:44
par Progi1984
L'ordre des lignes dans LL_Lines() est important, car elles sont rentrés au fur et à mesure de la lecture du fichier ASM original.
En fait ce morceau extrait simplement le code correspondant à une certaine fonction pour l'écrire dans un fichier (fichier stocké dans la chaine sASMContent avant écriture).
Vous voyez ce que je veux dire ?
Publié : jeu. 23/avr./2009 8:58
par brossden
Je pense avoir compris ce que tu veux faire. Selon moi tu veux faire un pseudo compilateur qui reprend tes lignes de code et qui les remplace par la fonction s'y rapportant. Si ce n'est pas cela merci d'être un peu plus explicite !
Publié : jeu. 23/avr./2009 10:00
par Progi1984
Je t'explique :
C'est pour le projet Moebius : projet francais "concurrent" de Tailbite.
Cette partie du code réécrit dans des fichiers distincts le code ASM pour chaque procédure.
Mais la lenteur ne se fait pas le parsage de la liste chainées, mais dans l'ajout à la fin du code de la ligne de la chaine qui contient ce code ASM, qui ralentit le parsage.
En fait, la liste chainée contient chq ligne du code ASM et la fonction référente. J'ai besoin d'écrire ces lignes dans un fichier spécifique par fonction.
Publié : jeu. 23/avr./2009 10:17
par brossden
Je pense avoir compris alors tu peux essayer le code suivant et merci de me dire si tu gagnes quelque chose :
Code : Tout sélectionner
; si on admet que ta chaine fera au maximum 1 Mo, mais il reste possible
de l'adapter par une autre valeur
*Mem = AllocateMemory(1000000)
Pointeur.q=0
ForEach LL_Lines()
If LL_Lines()\Function = LL_DLLFunctions()\FuncName
PokeS(*Mem + Pointeur,LL_Lines()\line + #System_EOL)
Pointeur + Len(LL_Lines()\line + #System_EOL)
EndIf
Next
sASMContent = PeekS(*Mem,Pointeur")
FreeMemory(*Mem)
Publié : jeu. 23/avr./2009 10:33
par gnozal
Progi1984 a écrit :... Mais la lenteur ne se fait pas le parsage de la liste chainées, mais dans l'ajout à la fin du code de la ligne de la chaine qui contient ce code ASM, qui ralentit le parsage...
Si c'est l'ajout des chaînes qui est critique, tu pourrais utiliser un 'string builder', théoriquement plus rapide qu'une concaténation de chaînes :
http://www.purebasic.fr/english/viewtopic.php?t=13015 (non testé).
Publié : jeu. 23/avr./2009 11:00
par Progi1984
Juste un tit test assez concluant :
Code : Tout sélectionner
Structure StringBuilder
pString.l
StringSize.l
MemSize.l
BlockSize.l
InitDone.l
; Initialized to 0 (FALSE) at creation. Means by default
; we have not initialized the structure/class.
EndStructure
Procedure.l sbCreate(BlockSize.l)
;
Protected *sbClass.StringBuilder
;
*sbClass = AllocateMemory(SizeOf(StringBuilder))
;
If *sbClass\InitDone : FreeMemory(*sbClass\pString) : EndIf
; If the stringbuilder is already initialized, free the memory of the string.
; BlockSize min. 1024 ($400) Byte
If BlockSize < $400 : BlockSize = $400 : EndIf
; BlockSize max. 1 MByte ($100000) Byte
If BlockSize > $100000 : BlockSize = $100000 : EndIf
;
If BlockSize <> (BlockSize & $FC00)
BlockSize = (BlockSize & $FC00) + 1024
EndIf
;
*sbClass\BlockSize = BlockSize
*sbClass\StringSize = 0
*sbClass\pString = AllocateMemory(BlockSize)
; Allocate the memory needed for our string
If *sbClass\pString <> 0
; Allocation went fine, let the structure know we initialized everything fine.
*sbClass\InitDone = #True
*sbClass\MemSize = *sbClass\BlockSize
; Set our memory size used to the size of the block.
Else
; Problem with allocation - let it know we did not initialize
*sbClass\InitDone = #False
*sbClass\MemSize = 0
EndIf
;
ProcedureReturn *sbClass
; Return the pointer to our new stringbuilder class.
EndProcedure
Procedure sbClear(*inSBClass.StringBuilder)
;
If *inSBClass\InitDone
FreeMemory(*inSBClass\pString)
*inSBClass\pString = 0
*inSBClass\StringSize = 0
*inSBClass\BlockSize = 0
*inSBClass\InitDone = #False
*inSBClass\MemSize = 0
EndIf
;
EndProcedure
Procedure sbDestroy(*inSBClass.StringBuilder)
;
If *inSBClass\InitDone
FreeMemory(*inSBClass\pString)
*inSBClass\pString = 0
*inSBClass\StringSize = 0
*inSBClass\BlockSize = 0
*inSBClass\InitDone = #False
*inSBClass\MemSize = 0
EndIf
;
FreeMemory(*inSBClass)
;
EndProcedure
Procedure sbAdd(*inSBClass.StringBuilder, inString.l)
;
Protected StrLen.l
Protected pNewString.l
Protected NewMemSize.l
Protected NewStringSize.l
;
StrLen = MemoryStringLength(inString)
;
NewStringSize = StrLen + *inSBClass\StringSize
;
If NewStringSize + 1 > *inSBClass\MemSize
NewMemSize = *inSBClass\MemSize + *inSBClass\BlockSize
pNewString=AllocateMemory(NewMemSize)
If pNewString = 0 : ProcedureReturn #False : EndIf
CopyMemory(*inSBClass\pString, pNewString, *inSBClass\StringSize)
FreeMemory(*inSBClass\pString)
*inSBClass\pString = pNewString
*inSBClass\MemSize = NewMemSize
EndIf
;
CopyMemory(inString, *inSBClass\pString + *inSBClass\StringSize, StrLen)
*inSBClass\StringSize = NewStringSize
;
EndProcedure
Procedure sbAddLiteral(*inSBClass.StringBuilder, inString.s)
;
Protected sAddress.l
Protected StrLen.l
Protected pNewString.l
Protected NewMemSize.l
Protected NewStringSize.l
;
sAddress = @inString
StrLen = MemoryStringLength(sAddress)
;
NewStringSize = StrLen + *inSBClass\StringSize
;
If NewStringSize + 1 > *inSBClass\MemSize
NewMemSize = *inSBClass\MemSize + *inSBClass\BlockSize
pNewString=AllocateMemory(NewMemSize)
If pNewString = 0 : ProcedureReturn #False : EndIf
CopyMemory(*inSBClass\pString, pNewString, *inSBClass\StringSize)
FreeMemory(*inSBClass\pString)
*inSBClass\pString = pNewString
*inSBClass\MemSize = NewMemSize
EndIf
;
CopyMemory(sAddress, *inSBClass\pString + *inSBClass\StringSize, StrLen)
*inSBClass\StringSize = NewStringSize
;
EndProcedure
Procedure.s sbGetString(*inSBClass.StringBuilder)
;
Protected WholeString.s
;
WholeString = PeekS(*inSBClass\pString)
;
ProcedureReturn WholeString
;
EndProcedure
Procedure.s sbGetStringAndDestroy(*inSBClass.StringBuilder)
;
Protected WholeString.s
;
WholeString = PeekS(*inSBClass\pString)
sbDestroy(*inSBClass)
;
ProcedureReturn WholeString
;
EndProcedure
Procedure.l sbLength(*inSBClass.StringBuilder)
Protected iLength.l
iLength = *inSBClass\StringSize
ProcedureReturn iLength
EndProcedure
Start = ElapsedMilliseconds()
sHold.s = "1"
sDelimiter.s = Chr(13)+Chr(10)
q.l = sbCreate(2048)
; Create a new string builder with a blocksize of 2048. You can create as many as you like. Just use a new long variable and pass it as a reference to the various functions.
For Inc = 0 To 180000
sbAdd(q, @sHold)
; Add a string by the address of the string variable
sbAdd(q, @sDelimiter)
sbAddLiteral(q, "Hi!")
Next
; Add by string rather than string address.
Debug sbGetString(q)
; Return the string itself
Debug "Length: "+Str(sbLength(q))
; Return the character count - 1 based. So "Hi" will return 2. Our example here should return 5.
sbDestroy(q)
; Destroy the string builder and clean up the used memory.
Debug ElapsedMilliseconds() - Start
Start = ElapsedMilliseconds()
sContent.s = ""
For Inc = 0 To 180000
sContent + sHold
sContent + sDelimiter
sContent + "Hi!"
Next
Debug sContent
Debug "Length: "+Str(Len(sContent))
Debug ElapsedMilliseconds() - Start
Avec d'assez bons résultats :
Publié : jeu. 23/avr./2009 22:04
par Progi1984
C'est décidé, je kiffe ce code ! Trop puissant !!!!!!!!