Map PureBasic vs Tableau associatif PHP7

Vous avez une idée pour améliorer ou modifier PureBasic ? N'hésitez pas à la proposer.
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Map PureBasic vs Tableau associatif PHP7

Message par G-Rom »

cela n'a pas d'impact sur le temps d’exécution , en l'augmentant considérablement ( x10 ) on triple les temps d'accès.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par Ollivier »

Ah! C'est dérangeant ça...
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par Ollivier »

Les performances d'un accès à une map sont-elles établissables dans l'espace en fonction du nombre de slots, d'une part, et en fonction du nombre d'éléments, d'autre part ?
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par erix14 »

Bonjour à tous,

J'avais déjà essayé avec les pointeurs, c'est pour cela que j'avais ajouté une variable de contrôle. Avec le code de Fred, le prénom de la Reference9999 est Pierre 200000, ce n’est donc pas bon...
D'ailleurs si on ajoute un => Debug MapSize(Societe("PureBasic")\Service("Commercial")\Employe()), mon code renvoie bien 200000 employés, alors que le code de Fred 0.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par Ollivier »

Bon, ce n'est pas très impartial mais ça,ça fournit une adresse (ici *x) à partir d'une clé ("savamment" préparée par les boucles For...Next car la fonction Str() est trop globale, donc "lente", il manque un "StrDigit", je n'en sais rien).

Alors je ne sais pas si l'on peut parler de slot (non, car absence de gestion des collisions). Mais là, il y a 16 millions de "machins" qui servent à indexer les entités.

En tout cas, ce qui sûr, c'est que 200000 entrées s'attribuent un age (28 ans) pointé par *x.

Code : Tout sélectionner

Global Dim B((1 << 24) - 1)
#ISi = SizeOf(Integer)
*x = AllocateMemory(#ISi)
PokeI(*x, 28)
mSize = 8


Lap0 = ElapsedMilliseconds()
Nom.S = "000000Age"
an = @Nom
For I5 = 0 To 1
	PokeA(an, I5)
	For I4 = 0 To 9
		PokeA(an + 1, I4)
		For I3 = 0 To 9
			PokeA(an + 2, I3)
			For I2 = 0 To 9
				PokeA(an + 3, I2)
				For I1 = 0 To 9
					PokeA(an + 4, I1)
					For I0 = 0 To 9
						PokeA(an + 5, I0)
						mBuffer = @Nom
						Key = CRC32Fingerprint(mBuffer, mSize)
						Key & $FFFFFF
						If B(Key)
							C + 1
						EndIf
						B(Key) = *x
						N + 1
					Next
				Next
			Next
		Next
	Next
Next
Lap1 = ElapsedMilliseconds()

MessageRequester(Str(n) + " entité(s)", "Durée de charge : " + Str(Lap1 - Lap0) + "ms // Collisions :" + Str(C) )
 
G-Rom
Messages : 3627
Inscription : dim. 10/janv./2010 5:29

Re: Map PureBasic vs Tableau associatif PHP7

Message par G-Rom »

erix14 a écrit :Bonjour à tous,

J'avais déjà essayé avec les pointeurs, c'est pour cela que j'avais ajouté une variable de contrôle. Avec le code de Fred, le prénom de la Reference9999 est Pierre 200000, ce n’est donc pas bon...
D'ailleurs si on ajoute un => Debug MapSize(Societe("PureBasic")\Service("Commercial")\Employe()), mon code renvoie bien 200000 employés, alors que le code de Fred 0.

@Fred, J'avais pas fait gaffe au contrôle, ton code n'est donc pas bon du tout. comment ca ce fait que l'on ne puisse pas pointé sur un élément d'une map lors de l'insertion (comme tu l'as fait) ?
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par erix14 »

Du coup, comme Fred croit que son code est correct et super rapide, il ne repassera peut-être pas par là...
Mon but, c'est de me rapprocher le plus possible de la syntaxe de PHP, et qu'une ligne de PHP = une ligne de PureBasic.
Mais pour faire plaisir à tout le monde, voici le code de Fred corrigé avec pointeur et création de 200000 sociétés, services et employés différents pour faire plaisir à falsam.
PureBasic :

Code : Tout sélectionner

EnableExplicit
Global t.L, TimeDebut.q, TimeFin.q
Structure Employe
	Prenom.s
	Nom.s
	Age.L
EndStructure
Structure Service
	Map Employe.Employe()
EndStructure
Structure Societe
	Map Service.Service()
EndStructure
Global NewMap Societe.Societe()
TimeDebut = ElapsedMilliseconds()
For t=1 To 200000
	Define *a.Employe = AddMapElement(Societe("PureBasic"+Str(t))\Service("Commercial"+Str(t))\Employe(), "Reference"+Str(t))
	With *a
		\Prenom = "Pierre "+Str(t)
		\Nom = "Dupond"
		\Age = 28
	EndWith
Next
Global Controle.s = "Prénom du commercial Reference9999 : "+Societe("PureBasic9999")\Service("Commercial9999")\Employe("Reference9999")\Prenom + Chr(10)
TimeFin = ElapsedMilliseconds()
MessageRequester("Temps d'exécution", Controle + Str( TimeFin - TimeDebut ) + " ms", #MB_OK)
PHP7 :

Code : Tout sélectionner

<?php
	$time_start = microtime(true);
	$TEmployes = array();
	for($t=1;$t<=200000;$t++){
		$TEmployes['PureBasic'.$t]['Commercial'.$t]['Reference'.$t] = array(
			'Prenom'=>'Pierre '.$t,
			'Nom'=>'Dupond',
			'Age'=>28
		);
	}
	$Controle = 'Prénom du commercial <b>Reference9999</b> : '.$TEmployes['PureBasic9999']['Commercial9999']['Reference9999']['Prenom'].'<br/>';
	
	$time_end = microtime(true);
	$time = $time_end - $time_start;
	
	echo $Controle.'Temps : '.($time*1000).' ms';
?>
PHP7 ne fait qu'enfoncer le clou, passant à 134 ms quand PureBasic passe à 5710 ms.
Avant de soumettre ce problème de performance des Map, j'avais bien retourné le problème dans tous les sens. J'avais juste réussi à diviser le temps de PureBasic par 2 avec un traitement parallèle "Parallel.For".
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par Ollivier »

@Erix14

A priori, c'est l'utilisation d'un pointeur interne qui manquerait à Purebasic. En gros, une autre directive que With serait une solution.

Pour info, lors du test du ci-dessus, j'ai été étonné par le temps d'allocation des chaînes. Cela n'a peut-être rien à voir mais PHP ne fait-il pas une allocation initiale de chaînes par défaut? Dès lors, les tests comparatifs sont moins équitables.
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par erix14 »

@Ollivier, With est une macro, que l'on mette ça :

Code : Tout sélectionner

With *a 
	\Prenom = "Pierre "+Str(t) 
	\Nom = "Dupond" 
	\Age = 28 
EndWith 
ou ça :

Code : Tout sélectionner

	*a\Prenom = "Pierre "+Str(t)
	*a\Nom = "Dupond"
	*a\Age = 28
le résultat est le même, heureusement !

Pour les allocations de chaine, il n'y a aucun souci avec PureBasic, le temps d'exécution ne représente que 79ms :

Code : Tout sélectionner

EnableExplicit
Global t.L, TimeDebut.q, TimeFin.q
Structure Employe
	Prenom.s
	Nom.s
	Age.L
EndStructure
TimeDebut = ElapsedMilliseconds()
For t=1 To 200000
	Define Societe.s = "PureBasic"+Str(t)
	Define Service.s = "Commercial"+Str(t)
	Define Employe.s = "Reference"+Str(t)
	Define a.Employe
	With a
		\Prenom = "Pierre "+Str(t)
		\Nom = "Dupond"
		\Age = 28
	EndWith
Next
TimeFin = ElapsedMilliseconds()
MessageRequester("Temps d'exécution", Str( TimeFin - TimeDebut ) + " ms", #MB_OK)
Autre précision, j'utilise PHP7 64bit et PureBasic 32bit, si je passe à PureBasic 64bit l'écart se creuse encore avec 8457ms.
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Map PureBasic vs Tableau associatif PHP7

Message par PAPIPP »

Bonjour à tous

Bien qu’une table MAP soit normalement optimisée pour une recherche et que le chargement ne soit réalisé normalement qu’une seule fois.
Voici une tentative de chargement avec la structure d’ERIX14.
Cet essai est basé sur une programmation structurée de la façon suivante :

Avec pour explication de { qui signifie pour chaque entité placée à gauche.

Ensemble des sociétés {So sociétés { Se services /société { em employés/société/service

Le temps de chargement sont réduits dans un rapport de 50 à 100

Code : Tout sélectionner

Global t.L,TimeDebut.q,TimeFin.q
Structure Employe
  Prenom.s
  Nom.s
  Age.L
EndStructure
Structure Service
  ;   serv.s  ; On peut ici placer des informations relatives  aux services
  Map Employe.Employe()
EndStructure
Structure Societe
  ;   soc.s  ; On peut ici placer des informations relatives  aux sociétés
  Map Service.Service()
EndStructure
Global NewMap Societ.Societe()
TimeDebut=ElapsedMilliseconds()
; chargement de la Map principale
;************  Début sociétés *************
For so=1 To 1000
  ;   societ("so"+Str(i))\soc="soc"+Str(so)
  societ("so"+Str(so))
; ************ Début services /sociétés ************  
  For se=1 To 10
    societ()\Service("se"+Str(se))
; ************* Début employés /sosciétés/services ***********    
    For em=1 To 20
;       societ()\Service()\Employe(Str(i)+Str(s)+Str(em))
      societ()\Service()\Employe(Str(em))
        societ()\Service()\Employe()\Age=28+em
        societ()\Service()\Employe()\Nom="Dupond"+Str(em)
        societ()\Service()\Employe()\Prenom="Pierre"+Str(em)
    Next
  Next
Next
timeFin=ElapsedMilliseconds()
Nbsoc=MapSize(societ())
nbserv=MapSize(societ()\Service())
nbemploy=MapSize(societ()\Service()\Employe())
Totalenr.l=Nbsoc*nbserv*nbemploy
MessageRequester("Temps d'exécution",Str(TimeFin-TimeDebut)+" ms"+Chr(10)+"nb societé="+Str(nbsoc)+Chr(10)+"NB service/soc ="+Str(nbserv)+Chr(10)+"Nb employé/service="+Str(nbemploy)+Chr(10)+"Nb Total="+Str(Totalenr),#MB_OK)
End
PS : il serait intéressant de savoir si l'option MAP de PB est mieux ou plus mal optimisée que PHP sur les demandes d'infos et non sur le chargement.
A+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Fred
Site Admin
Messages : 2652
Inscription : mer. 21/janv./2004 11:03

Re: Map PureBasic vs Tableau associatif PHP7

Message par Fred »

Effectivement j'ai été un peu vite :). Le probleme ici est que c'est n'est pas le meme genre de container. Tu simules un tableau associatif PHP avec une map de map de map, mais c'est pas vraiment fait pour ca car une nouvelle map complete (avec sa lookup table) est créée pour chaque élément. Ca prend beaucoup de RAM et de temps.

Apres, si tu veux continuer dans cette voie, tu peux augmenter le nombre de slot de la lookup table lors de l'initialisation de la map:

Code : Tout sélectionner

EnableExplicit
Global t.L, TimeDebut.q, TimeFin.q
Structure Employe
   Prenom.s
   Nom.s
   Age.L
EndStructure
Structure Service
   Map Employe.Employe()
EndStructure
Structure Societe
   Map Service.Service()
EndStructure
Global NewMap Societe.Societe(100000)
TimeDebut = ElapsedMilliseconds()
For t=1 To 200000
   Define *a.Employe = AddMapElement(Societe("PureBasic"+Str(t))\Service("Commercial"+Str(t))\Employe(), "Reference"+Str(t))
   With *a
      \Prenom = "Pierre "+Str(t)
      \Nom = "Dupond"
      \Age = 28
   EndWith
Next
Global Controle.s = "Prénom du commercial Reference9999 : "+Societe("PureBasic9999")\Service("Commercial9999")\Employe("Reference9999")\Prenom + Chr(10)
TimeFin = ElapsedMilliseconds()
MessageRequester("Temps d'exécution", Controle + Str( TimeFin - TimeDebut ) + " ms", #MB_OK)
Ca reduit un peu le temps de remplissage.
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par erix14 »

@PAPIPP, mon but c'est de pouvoir travailler avec les map pour avoir des codes plus souples, plus petits, plus verbeux, comme cet exemple :

Code : Tout sélectionner

Structure T
	Map T.T()
	ValS.s
	StructureUnion
		ValL.l
		ValF.f
	EndStructureUnion
EndStructure
Global NewMap TData.T()

With TData("PureBasic")\T("Commercial")\T("001")
	\T("Prenom")\ValS = "Pierre"
	\T("Nom")\ValS = "Dupond"
	\T("Age")\ValL = 25
	\T("Passe-temps")\T("Lecture")
	\T("Passe-temps")\T("Randonnée")
EndWith
With TData("PureBasic")\T("Commercial")\T("002")
	\T("Prenom")\ValS = "Paul"
	\T("Nom")\ValS = "Martin"
	\T("Age")\ValL = 29
	\T("Passe-temps")\T("Voyage")
	\T("Passe-temps")\T("Jeux vidéo")
EndWith
With TData("PureBasic")\T("Administratif")\T("003")
	\T("Prenom")\ValS = "Jean"
	\T("Nom")\ValS = "Moulin"
	\T("Age")\ValL = 41
EndWith
With TData("PureBasic")\T("Technique")\T("004")
	\T("Prenom")\ValS = "Fred"
	\T("Nom")\ValS = "Leboss"
	\T("Age")\ValL = 39
	\T("Passe-temps")\T("Jeux vidéo")
EndWith
With TData("Microsoft")\T("Commercial")\T("001")
	\T("Prenom")\ValS = "Nicole"
	\T("Nom")\ValS = "Duchemin"
	\T("Age")\ValL = 33
	\T("Passe-temps")\T("Lecture")
EndWith
With TData("Microsoft")\T("Technique")\T("002")
	\T("Prenom")\ValS = "Gérald"
	\T("Nom")\ValS = "Durand"
	\T("Age")\ValL = 38
EndWith

Global NewMap TSocietes.T()
Global NewMap TSocietesTotalAge.T()
Global NewMap TServices.T()
Global NewMap TServicesTotalAge.T()
Global NewMap TPasseTemps.T()
Debug "-----------------------------------"
Debug "Liste du personnel toutes sociétés confondues :"
ForEach TData()
	Global Societe.s = MapKey(TData())
	ForEach TData(Societe)\T()
		Global Service.s = MapKey(TData(Societe)\T())
		ForEach TData(Societe)\T(Service)\T()
			Global Reference.s = MapKey(TData(Societe)\T(Service)\T())
			With TData(Societe)\T(Service)\T(Reference)
				Debug Societe + " : " + \T("Prenom")\ValS + " " + \T("Nom")\ValS + " " + Str(\T("Age")\ValL) + " ans (Réf : " + Reference + ")"
				TSocietes(Societe)\ValL + 1
				TSocietesTotalAge(Societe)\ValL + \T("Age")\ValL
				TServices(Service)\ValL + 1
				TServicesTotalAge(Service)\ValL + \T("Age")\ValL
			EndWith
			ForEach TData(Societe)\T(Service)\T(Reference)\T("Passe-temps")\T()
				TPasseTemps(MapKey(TData(Societe)\T(Service)\T(Reference)\T("Passe-temps")\T()))\ValL + 1
			Next
		Next
	Next
Next
Debug "-----------------------------------"
Debug "Âge moyen par société :"
ForEach TSocietes()
	Debug MapKey(TSocietes()) + " : " + StrF( TSocietesTotalAge(MapKey(TSocietes()))\ValL / TSocietes()\ValL ) + " ans"
Next
Debug "-----------------------------------"
Debug "Âge moyen par service :"
ForEach TServices()
	Debug MapKey(TServices()) + " : " + StrF( TServicesTotalAge(MapKey(TServices()))\ValL / TServices()\ValL ) + " ans"
Next
Debug "-----------------------------------"
Debug "Liste des passe-temps :"
ForEach TPasseTemps()
	Debug MapKey(TPasseTemps()) + " : " + Str(TPasseTemps()\ValL) + " fois"
Next
@Fred, merci, oui ça réduit le temps de remplissage, donc on fera avec le temps que tu nous fasses une optimisation à la PHP.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par Ollivier »

@Erix14

Je ne pense pas me planter. Il faut une directive "with" supplémentaire qui fasse pointer sur un résultat beta-réduit, non sur une expression.

Code : Tout sélectionner

Macro WithExtended(AssociatedStructure, Expression)
*InternalTemporaryPointor.AssociatedStructure = Expression
With *InternalTemporaryPointor
EndMacro
Si, dans ton tout dernier code, tu fais actuellement le remplacement "à la main", en t'inspirant de cette macro impossible ci-dessus et que tu insères $FFFFFF (24 bits) dans chaque parenthèse des Newmaps, quelle chronométrie obtiens-tu?
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par Ollivier »

G-Rom a écrit : cela n'a pas d'impact sur le temps d’exécution , en l'augmentant considérablement
( x10 ) on triple les temps d'accès.
Je viens de tester les maps. Je découvre car je n'avais pas besoin des commandes natives pour les maps. Théoriquement, je ne m'attendais pas à des *100 en accélération, en augmentant la quantité de slots, juste à un *1.5 un *2 voire *3, mais là, c'est *1/75 !?!

Plus la doc qui indique le contraire...
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Re: Map PureBasic vs Tableau associatif PHP7

Message par erix14 »

@Ollivier, pour ta macro, on ne peut pas mettre un With dans une Macro.
Si je mets $FFFFFF dans toutes les déclarations de map, j'ai ma mémoire plante.

Après des tests plus poussés sur les slots, je m'aperçois que le problème de PureBasic, c'est surtout un problème de gestion de mémoire. Avec des Map a une dimension on peut rivaliser avec PHP en augmentant les slots, mais avec des Map a dimension infini, on ne peut pas... C'est pour cela que Fred doit allouer de la mémoire global pour toutes créations de map, au lieu de faire du cas par cas.
Répondre