Performances Tableau Interprocess moderne

Bonjour

Je profite du calme de la période pour démarrer un nettoyage de ma base pour supprimer les tableaux inter process de ma base afin de m’orienter vers le mode préamptif…

Je commence par un truc con, remplacer le nom des jours que j’ai dans un tableau inter process bien pratique <>NomsJours contenant Lundi, Mardi, Mercredi etc…

Je me suis dis que j’allais tester plusieurs solutions

  1. Le tableau inter process classique
  2. Une fonction écrite en dur*
  3. Une collection partagée dans le Storage
  4. Une recherche directe dans la BDD en mode classique (CHERCHER)
  5. Une recherche directe dans la BDD en mode ORDA (query)
  • J’ai souvenir que 4D disait à une époque que c’était lent d’appeler une méthode.

Voici les résultats que j’ai sur une boucle x1000 de chaque test Interprété / Compilé, je les ai refait plusieurs fois sans trop de différence

  1. Le tableau inter process classique = 2ms / 0ms
  2. Une fonction écrite en dur* = 34ms / 0ms
  3. Une collection partagée dans le Storage = 2ms / 1ms
  4. Une recherche directe dans la BDD en mode classique (CHERCHER) = 24ms / 21ms
  5. Une recherche directe dans la BDD en mode ORDA (query) = 2914ms / 1281ms

Voila mes conclusions :

  1. La collection a l’air d’être la meilleure solution, j’ai poussé le test à x100000 pour comparer au tableau inter process et à la méthode en dur, j’ai 5ms pour le tableau inter process, 8ms pour la méthode en dur et 93ms pour la collection en compilé. c’est 20x plus lent mais bon ça reste raisonnable.

  2. Est-ce que ma façon de tester est bonne ? j’ai peut être un truc qui cloche dans ma méthode de test

  3. Pourquoi la query ORDA est-elle si lente par rapport à la recherche à l’ancienne, j’ai fait une connerie ?

  4. Est-ce que vous auriez un code encore mieux ? (dommage qu’on est pas des constantes en tableaux).

Voici le code

Méthode : Test

// Variables interprocess
$time:=Nombre de millisecondes
Boucle ($i;1;1000)
$result:=<>zNomJours{4}
Fin de boucle
$time1:=Nombre de millisecondes-$time

// Fonction écrite en dur
$time:=Nombre de millisecondes
Boucle ($i;1;1000)
$result:=zNomJour (4)
Fin de boucle
$time2:=Nombre de millisecondes-$time

TABLEAU TEXTE($jours;0)
zDoc2Tableau (“Nom Jours”;->$jours)
$cjours:=Créer collection partagée($jours)
TABLEAU VERS COLLECTION($cjours;$jours)
Utiliser (Storage)
Storage.cjours:=$cjours
Fin utiliser

// Utilisation d’une collection partagée
$time:=Nombre de millisecondes
Boucle ($i;1;1000)
$result:=Storage.cjours[4]
Fin de boucle
$time3:=Nombre de millisecondes-$time

// Recherche dans la table à l’ancienne
$time:=Nombre de millisecondes
Boucle ($i;1;1000)
CHERCHER([Documents];[Documents]Nom=“Noms Jours”)
$result:=[Documents]Données.Tableau[4]
Fin de boucle
$time4:=Nombre de millisecondes-$time

// Recherche dans la table en ORDA
$time:=Nombre de millisecondes
Boucle ($i;1;1000)
$result:=ds.Documents.query(“Nom = ‘Nom Jours’”).Données.Tableau[4]
Fin de boucle
$time5:=Nombre de millisecondes-$time

ALERTE(Chaîne($time1)+" - “+Chaîne($time2)+” - “+Chaîne($time3)+” - “+Chaîne($time4)+” - "+Chaîne($time5))

Méthode zNomJour :

Au cas ou
: ($1=1)
$0:=“Lundi”
: ($1=2)
$0:=“Mardi”
: ($1=3)
$0:=“Mercredi”
: ($1=4)
$0:=“Jeudi”
: ($1=5)
$0:=“Vendredi”
: ($1=6)
$0:=“Samedi”
: ($1=7)
$0:=“Dimanche”
Fin de cas

Merci :slight_smile:

Hello,
très rapidement…
je suppose que c’est en mono ? si oui, essaie en C/S pour la partie database.

Bonjour,

Pour ORDA, je vois que vous faîtes:

$result:=ds.Documents.query(“Nom = ‘Nom Jours’”).Données.Tableau[4]

ds.Documents.query(“Nom = ‘Nom Jours’”) retourne une entity selection (et non une entity).

Si vous êtes sûr, que cette entity selection contient toujours une seule entity, vous pouvez faire

ds.Documents.query(“Nom = ‘Nom Jours’”).first().Données.Tableau[4]

Pour la partie sur la collection partagée:

$cjours:=Créer collection partagée($jours)

$jours est un tableau et il me semble que les tableaux ne sont pas supportés comme paramètre

https://doc.4d.com/4Dv18R2/4D/18-R2/New-shared-collection.301-4803743.en.html

Bonjour

Un grand merci pour vos messages :slight_smile: :slight_smile:

  1. Alors j’ai testé en C/S, exactement les mêmes résultats
  2. J’ai essayé la recherche ORDA avec .first(), c’est pareil pour les performances
  3. Pour les tableaux dans les collections partagées, ça marche très bien, j’accède bien à ma donnée d’un autre process web. Pour l’instant c’est ma seule option viable.

Sinon comment faites-vous pour avoir lundi mardi etc… ? y’a pas plus simple ?, des fois je me demande si je me tourmente pas l’esprit !

Une autre question va suivre, que conseillerais 4D pour des tableaux inter-process qui mémorisent par exemple du cache ou un historique de requêtes web ou des trucs qui sont sensé occuper un paquet de mémoire (sans exagérer non plus)

Dans mes bases actuelles, j’ai beaucoup utiliser les tableaux inter-process pour mémoriser un tas de trucs, est-ce que je peux tout mettre dans Storage ?

: Olivier FAURE

Sinon comment faites-vous pour avoir lundi mardi etc… ?
Je me rappelle de solutions évoquées ici du type : parser 7 dates consécutives dans un format bavard avec une regex, ça doit prendre des microsecondes…
Miyako a sûrement déjà fait ça en 3 solutions différentes !

Si ça peut t’inspirer, j’ai retrouvé cette méthode dans mes archives.
Ce n’est sûrement pas de moi et devrait être adapté pour l’anglais.

<code 4D>
// DAT_Month_in_letters bernard //
If (True)
// 066138BE424D44EAA3077E9E9177D978
//
//________________________________________________________________________________
//DESCRIPTION FONCTIONNELLE
//Cette méthode retourne en lettres le mois d’une date, dans la langue passée en paramètre 2.
//Ne fonctionne pas en anglais à cause de l’inversion
//
//________________________________________________________________________________
//AMÉLIORATIONS À APPORTER
//
//________________________________________________________________________________
//CRÉATION par Bernard Escaich
//•1• 10/02/2018 12:40:51
//
//________________________________________________________________________________
//COMPOSANT
//
//________________________________________________________________________________
//PARAMÈTRES
C_DATE($1) //
C_TEXT($2) //
/// //
//________________________________________________________________________________
//TYPAGE DES VARIABLES LOCALES
C_BOOLEAN($OK_b) //
C_DATE($Date_d) //
C_LONGINT($Nb_Parameters_l) //
C_TEXT($Lang_current_t) //
C_TEXT($Lang_t) //
C_TEXT($Month_t) //
//
//TYPAGE DES VARIABLES à reclasser dans les COMPILER_XXX //
//TYPAGE DES VARIABLES INTERPROCESS à reclasser //
//________________________________________________________________________________
//CONTROLE DES PARAMÈTRES
$Nb_Parameters_l:=Count parameters
If ($Nb_Parameters_l>=1)
//Contrôle des paramètres dans le cas d’utilisation normale de la méthode
If ($Nb_Parameters_l>=1)
$Date_d:=$1
If ($Date_d=!00-00-00!)
$Date_d:=Current date()
End if
Else
$Date_d:=Current date(
)
End if
$OK_b:=True
If ($Nb_Parameters_l>=2)
$Lang_t:=$2
End if
End if
//
//________________________________________________________________________________
//INITIALISATION DES VARIABLES LOCALES
//
//________________________________________________________________________________
//INITIALISATION DES VARIABLES GLOBALES
//
End if
//________________________________________________________________________________
//EXÉCUTION
If ($OK_b)
$Lang_current_t:=Get database localization(Current localization)
If ($Lang_t#$Lang_current_t)
SET DATABASE LOCALIZATION($Lang_t)
End if

$Date_d:=Current date
$Month_t:=String($Date_d;Internal date long)
$Month_t:=Substring($Month_t;Position(" ";$Month_t)+1)
$Month_t:=Substring($Month_t;1;Position(" ";$Month_t)-1)

If ($Lang_t#$Lang_current_t)
	SET DATABASE LOCALIZATION($Lang_current_t)
End if 

$0:=$Month_t

End if
//
//________________________________________________________________________________
//AUTOTEST
If ($Nb_Parameters_l=0)

$Month_t:=DAT_Month_in_letters (!1950-12-08!)
$Month_t:=DAT_Month_in_letters (!1950-12-08!;"en-en")
$Month_t:=DAT_Month_in_letters (!1950-12-08!;"de")

End if
//

</code 4D>

Merci mais Oula :slight_smile: je recherche la simplicité, ma méthode zNomjour irait très bien, je cherche quelque chose de + rapide et de plus propre, voire élégant si possible :slight_smile:

Trouves les ressources de 4D ou du système, tu auras la traduction en prime !

C’est vraiment la méthode en préamptif qui va me permettre d’avoir des tableaux de constantes en mémoire un peu comme du cache et pas uniquement les jours de la semaine, c’est un exemple.

Le Storage parait le meilleur moyen, par contre, j’ai bien chercher dans la doc, comment ré-initialise-t-on le Storage ?

J’ai essayé C_OBJET(Storage) (qui bloque 4D) et Storage:=Null qui ne fait rien…

Ou alors j’ai pas bien vu dans la doc

Merci :slight_smile:

Je viens de refaire des tests et je ne retrouve plus la lenteur extreme que j’avais en ORDA, elle reste néanmoins 4x plus lente qu’en recherche avec CHERCHER (mystère) :

J’ai rajouté un test avec les données dans une énumération.

Voici mon test sur 10000x chaque traitement

  1. Tableau inter process : 1ms
  2. Méthode zNomJour appelée : 1ms
  3. Utilisation de Storage + Collection partagée avec tableau : 4ms
  4. Utilisation de CHERCHER : 264ms
  5. Utilisation de ORDA : 635ms
  6. Utilisation d’une énumération vers tableau : 249ms

J’adopte le Storage.

Je réitère ma question : comment ré-initialise-t-on le Storage ? :slight_smile:

: Olivier FAURE

omment ré-initialise-t-on le Storage ?

Je ne sais pas comment les autres travaillent avec le storage, voici la mienne.

Je créée une méthode, ici Application detail storage. Le code qui suit n’est pas prévu pour être éditable mais je pense que que devrais être capable de trouver la ta façon de le faire.

<code 4D>
C_OBJECT($0)
Use (Storage)

If (Storage.detail=Null)
	
	Storage.detail:=New shared object
	
	Use (Storage.detail)
		
		Storage.detail.nom_application:="mes-contrat-maintenance"
		Storage.detail.version_application:="Version 2.4 Build"
		Storage.detail.build_application:=1088
		
	End use 
End if 

$0:=Storage.detail

End use

// EOM
</code 4D>

: Olivier FAURE

Je réitère ma question : comment ré-initialise-t-on le Storage ? :slight_smile:
Quitte et relance, c’est radical.
Plus sérieusement, j’ai pas trouvé mieux que nettoyer propriété par propriété :
<code 4D>
OB GET PROPERTY NAMES(Storage;$propriete_at)
Use (Storage)
For ($i;1;Size of array($propriete_at))
OB REMOVE(Storage;$propriete_at{$i})
End for
End use
</code 4D>

Bonjour

Merci pour ces deux messages,

  1. Je pensais qu’il fallait éviter les commandes OB… maintenant
  2. 4D devrait faire une base exemple unique avec une application multiple et complete de chaque fonctionnalité car là, avec le foisenemment de possibilités, on ne sait plus très bien quoi utiliser comment :slight_smile:

Entre les commandes Json, OB… et ORDA, ça devient très confus…

Merci encore, j’ai ce qu’il faut pour avancer :slight_smile:

: Olivier FAURE

ça devient très confus…

Dans mon exemple il faudrait inverser le if en ligne 4 et le use en ligne 2

Il faut éviter de mobiliser le storage (et perturber une autre opération en parallèle sur le storage) alors qu’ensuite on ne va rien faire en ligne 4

  1. Je pensais qu’il fallait éviter les commandes OB… maintenant
    De mémoire, Laurent Esnault disaient qu’elles étaient un peu moins performantes que la dot notation. Pour autant, si tu n’as rien d’équivalent en dot notation, y’a pas de raison.
  1. 4D devrait faire une base exemple unique avec une application
    multiple et complete de chaque fonctionnalité car là, avec le
    foisenemment de possibilités, on ne sait plus très bien quoi utiliser
    comment :slight_smile:
    Entre les commandes Json, OB… et ORDA, ça devient très confus…
    Hé oui, un seul summit manque et tout est dépeuplé… :mrgreen:

Salut,

Pourquoi pas une bonne vieille énumération ? Tu la charges dans un tableau local à la demande et tu en fais ce que tu veux. Pas de soucis de performances et plus de variables interprocess.

: Olivier FAURE
  1. 4D devrait faire une base exemple unique avec une application
    multiple et complete de chaque fonctionnalité car là, avec le
    foisenemment de possibilités, on ne sait plus très bien quoi utiliser
    commentSmile

La doc des versions 3 ou 4 était très bien faite avec des exemples assez globaux. Aujourd’hui il y a énormément d’informations mais c’est très confus et il n’y a guère plus d’exemple global.
Les bases HDI sont assez simplistes…
Ce qui manque, ce sont les principes et les bonnes pratiques.
L’exemple que j’ai soulevé l’autre avec OBJECT SET SUBFORM n’est décrit nulle part.

Je l’ai testée, moins rapide que Storage + Collection, pis bon ça fait tâche avec ORDA les énumérations… comme je ne fait plus que du web avec 4D, je ne sais plus rien au formulaires, boite à outils, menus, utilisateurs… je ne l’utilise que pour le langage, la base de donnée et le serveur web. Merci pour l’info en tout cas :slight_smile:

Ton exemple de test est aussi moyennement choisi (trop particulier). Car la liste des jours, c’est plus une liste constante, elle ne va pas énormément varier :roll:

C’est plus une ressource, donc l’histoire de l’Énumération n’est PAS à écarter d’un revers de la main.
J’irais même plus loin, une énumération à base de Xliff pour avoir la traduction des noms dans différentes langues.

Une fois cela défini, la question est plus comment tu accèdes à cette ressource. Est-ce que tu vas lire le fichier à chaque fois, ou stocker cette énumération en mémoire, etc.

À tester mais un simple fichier Xliff et utiliser la commande 4D Lire chaine dans liste

Pour ma part, pour la liste des mois, j’ai une énumération enregistrée dans ma base construite à partir de liens xliff et une méthode qui charge cette énumération dans un tableau local est retourne le nom que je veux en fonction du N° du mois par exemple. C’est très loin d’être optimisé, mais pour le peu de fois où c’est utilisé. Et je n’ai pas de variable interprocess ou tableau interprocess et cela répond à ce que je veux : la liste des mois dans la langue de mon interface.

La façon d’accéder à la ressource dépend de tes besoins en revanche la question : “où stocker cette ressource ?”, ne se pose pas à mon sens (Fichier(s) Xliff joints à ta base).

Ah merci :slight_smile: c’est très intéressant, je ne sais même pas comment fonctionne le xliff, d’ailleurs je vois pas le rapport avec les énumérations.

Alors j’ai pris les jours comme exemple mais ce n’est pas mon propos, je vais avoir une bonne 30aine de tableaux divers et variés qui n’ont rien à voir.

L’idée est d’avoir ces informations de type tableau ou tableau clé-valeur accessibles pour tous les process

On aurait eu des tableaux de constantes personnalisables ca aurait été top

Les énumérations c’est quand même 269ms contre 4ms pour les collections en storage.

Ta remarque me fait me demander : qu’as-tu contre les collections + storage ?

Merci en tout cas, c’est super vos réponses à tous :slight_smile: