11540 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Je suis en train de réaliser de réaliser une petite application Web qui me permet d'afficher une image sur mon serveur qui sera rafraîchie très fréquemment tel un flux vidéo.
De plus, j'ai besoin d'afficher des informations sur cette image (du texte), ce qui fait que j'utilise le framework JS Dojo pour dessiner un canvas et insérer mon image dedans.

Pour réaliser tout cela, j'appelle une fonction via setTimeout qui va :
- Dessiner un canvas une première fois et insérer l'image dedans
Les fois d'après, seule l'image sera rafraichie (le canvas n'est pas redessiné)
- Faire une requête Dojo Ajax pour récupérer le texte à afficher sur l'image (appel PHP et Mysql)
- Un nouveau setTimeout qui va rappeler cette fonction de nouveau

Mon problème est une grosse fuite mémoire que je n'arrive pas à localiser.
J'ai placé une variable que j'ai appelé "busy" qui passe à 1 dans le setTimeout. Si la boucle n'est pas finie, j'ai placé une condition de ne rien faire pour ne pas surcharger la boucle, mais rien n'y fait.

Voici en gros le code javascript dans ces grandes lignes :



mon_image.src = imageFileUrl + "?time=" + new Date().getTime();
mon_image.onload = function(ev_mon_image1){
	ev_mon_image1.cancelBubble = true;  // Utile ?
	setTimeout(refreshData, 200);
};


Et la fonction refreshData

function refreshData() {
	if(busy == 0){
		busy = 1;
		mon_image.src = imageFileUrl + "?time=" + new Date().getTime();
		mon_image.onload = function(ev_mon_image2){
			if(dessin_ok == 0) {
				dessiner(mon_image); // Fonction qui dessine le canvas avec dojox.gfx
				dessin_ok = 1;
			} else {                       
				image.setShape({src : mon_image.src});
				// Sinon, juste mise à jour de l'image dans le canvas
                        }

			if (ev_mon_image2.stopPropagation) {
			  ev_mon_image2.stopPropagation(); // Utile ?
			}
			ev_mon_image2.cancelBubble = true;
			
			dojo.xhrGet({
				url : "getData.php",
				sync : false,
				load: function(data) 
				{
					// Traitement du résultat
					busy = 0;
				}
			});
		};
	} else {
		busy = 0;
	}
	setTimeout(refreshData, 200);
}


Je comprends que mon process peut prendre plus de 200ms vu ce que je lui demande, c'est pourquoi j'ai mis le flag busy mais en vain.



Si je laisse mon application tourner, mon navigateur Firefox commence à consommer 160Mo de Ram et peut aller jusqu'à 600Mo très rapidement. Dans un moindre mal, Firefox en mode sans échec consomme de plus en plus de mémoire mais de manière beaucoup plus lente.

Merci d'avance de l'aide que vous pourrez m'apporter.

PS : Voici un aperçu de l'utilisation de ma mémoire. Les dents de scie sont à peu près régulières mais au bout d'un long moment, les "dents" ont tendance à monter de plus en plus haut.

upload/48237-alsa.PNG
Modifié par CaramelXS (08 Feb 2013 - 17:31)
bonjour, pourquoi mettre un else busy = 0 à la fin?
à chaque tour de settimeout:

si busy = 0 il passe à 1 et il travaille
au coup d'après si il est à 0 c'est qu'il avait fini donc il retravaille
par contre si il était à 1 le else lui dit de passer à zéro donc fini ou pas au coup d'après il redessine. Si tu enleves ce dernier else, à chaque tour si ce n'est pas fini il ne fera rien.

je ne laisserais l'initialisation de busy à zéro que dans le xhrGet comme tu l'as fait.

mais le mieux quand un canvas fait ramer c'est de vider ta fonction refreshData et de remettre tes lignes de codes bouts par bouts pour voir lequel fait monter en pic ton processeur dans le timout.

Je pense aussi que mettre un canvas pour y dessiner des images n'est peut être pas la meilleure solution. Dessiner des images dans un canvas coute des ressources (si ton image est grosse surtout) puis si ton image fait 100% du canvas, ca ne serait pas mieux de juste changer l'image qui est sur ta page en javascript (et son texte en position absolute par exemple) plutot que de la dessiner dans un canvas?
Modifié par canvasdev (08 Feb 2013 - 20:47)
Bonjour et merci pour cette réponse rapide. En effet, il y a une affectation de busy inutile, je la retirerai.
Je ne sais pas trop si je peux changer de manière d'afficher l image. Ma requête Ajax getdata.php me ramène ce fameux texte mais aussi des coordonnées de cadre que j affiche dans le Canvas. J ai déjà récupéré sur un autre projet les coordonnées proportionnellement à une image retaillée mais cela était assez coûteux en terme de développement. Sinon j ai essayé de tout de commenter dans le onload mais la mémoire reste au même point.
bonjour,

je ne connais pas grand chose a dojo , mais est-ce-que les images chargée précédemment sont vidé lors de l'arrivée de la nouvelle image (l'ancienne image reste en memoire et la nouvelle s'ajoute et ainsi de-suite....), par exemple essai de vider ton canvas et tes variables avant de lancer une nouvelle fois le script
Essai aussi peut-etre de ralentir la fréquence rafraichissement (la requete n'a pas le temps de se finir et reste en mémoire alors qu'une autre arrive) , 200ms c'est court...

voila voila bonne soirée Smiley smile
Regarde les outils de débogage de Google Chrome, notamment le profiler et la timeline. Tu auras un outil réellement adapté au débugging des fuites de mémoires en javascript.

Il y a pas mal de tutoriel en ligne expliquant comment s'en servir.
Merci pour ces réponses. Je vais appliquer tout cela quand je serai sur le pc concerné lundi et vous ferai rapidement un retour comme vous l'avez fait.
Bonsoir,
J'ai réalisé certains tests et j'ai rajouté avant cette ligne.

image.setShape({src : mon_image.src});


celle-ci

image.setShape({src : ''});


Cela semble assez bénéfique pour l'application puisque la mémoire monte encore, certes, mais de manière beaucoup plus lente. De plus, je constate que si je lance mon Firefox en mode "safe-mode", la mémoire consommée est encore plus basse. Même constat quand je touche au paramètre de fréquence du setTimeout que je ne peux pas trop relever car mon application se veut "en live".

Voilà, je continue à creuser. Merci encore
Modifié par CaramelXS (11 Feb 2013 - 18:00)