Aller au contenu

[Question] pourquoi si lent


Lightness1024

Recommended Posts

Salut, je suis nouveau ici. (bien que je connaisse le site depuis un moment je n'avais pas de compte, donc vala, bonjour tlm)

je suis en train de développer un pti jeu de puzzle bien connu pour m'entrainer et apprendre Android.

j'ai fait un système, pas très puissant je l'avoue, qui utilise une TableLayout et un TableRow pour faire une grille d'ImageButton (10*8 mettons).

j'ai une fonction qui fait une petite récursion pour chercher un groupe de boutons (composante connexe), ca doit a peine récursiver 4 ou 5 fois (autant que de boutons ds le groupe).

ca retourne un Vector<ImageButton>

apres je loop dessus, change la visibilité a faux.

bref je time cette opération avec System.nanoTime()

et je trouve des temps entre 200 et 320ms. (oui ms, j'ai donc fait (end - start) / 1000000)

ce qui est bien sur du grand n'importe quoi, sur un PC une telle opération aurait prit 100µs au grand maximum. (en C++ du moins, je connais pas les perfs de java encore)

d'où ma question:

qu'est-ce qui est lent ? les appels a la SDK ? le java ? le téléphone ? le fait d'être en debug attaché a éclipse ?

edit ps: j'ai bien simplifié en disant que je fais que looper et faire setVisibility, je loop encore pour swapper les boutons du dessus et les faire "tomber" dans le trou créé (en les swappant avec des cachés)... mais bon, tout ca c'est peanut. je peux poster du code si ca sert a qqch

Lien vers le commentaire
Partager sur d’autres sites

Avec un peu de code, ca serai déjà plus clair effectivement.

Sinon, juste pour voir, essaye d'enlever le setVisibility, et refait les mesures.

Salut, je suis nouveau ici. (bien que je connaisse le site depuis un moment je n'avais pas de compte, donc vala, bonjour tlm)

je suis en train de développer un pti jeu de puzzle bien connu pour m'entrainer et apprendre Android.

j'ai fait un système, pas très puissant je l'avoue, qui utilise une TableLayout et un TableRow pour faire une grille d'ImageButton (10*8 mettons).

j'ai une fonction qui fait une petite récursion pour chercher un groupe de boutons (composante connexe), ca doit a peine récursiver 4 ou 5 fois (autant que de boutons ds le groupe).

ca retourne un Vector<ImageButton>

apres je loop dessus, change la visibilité a faux.

bref je time cette opération avec System.nanoTime()

et je trouve des temps entre 200 et 320ms. (oui ms, j'ai donc fait (end - start) / 1000000)

ce qui est bien sur du grand n'importe quoi, sur un PC une telle opération aurait prit 100µs au grand maximum. (en C++ du moins, je connais pas les perfs de java encore)

d'où ma question:

qu'est-ce qui est lent ? les appels a la SDK ? le java ? le téléphone ? le fait d'être en debug attaché a éclipse ?

edit ps: j'ai bien simplifié en disant que je fais que looper et faire setVisibility, je loop encore pour swapper les boutons du dessus et les faire "tomber" dans le trou créé (en les swappant avec des cachés)... mais bon, tout ca c'est peanut. je peux poster du code si ca sert a qqch

Lien vers le commentaire
Partager sur d’autres sites

Avec un peu de code, ca serai déjà plus clair effectivement.

Sinon, juste pour voir, essaye d'enlever le setVisibility, et refait les mesures.

Salut :) merci pour la réponse.

j'ai essayé mais ca n'a rien changé.

donc j'ai rajouté des points de profiling plus précis pour déterminer en gros où le temps s'égare:

		long timestart = System.nanoTime();
		Vector<ImageButton> vimb = grid_manager.getConnectedComponent(_im);
		long timecomponent = System.nanoTime();
		for (ImageButton im : vimb)
		{
			grid_manager.markDeletedButton(im);
		}
		long timedelete = System.nanoTime();
		grid_manager.verticalFall();
		long timefall = System.nanoTime();
		grid_manager.horizontalCrunch();
		long timecrunch = System.nanoTime();
		End end = grid_manager.detectEnd();

		long timeend = System.nanoTime();

		Toast.makeText(getApplicationContext(), "it took :"
		               + "total:" + makeMsStr(timeend - timestart)
		               + " group:" + makeMsStr(timecomponent - timestart)
		               + " delete:" + makeMsStr(timedelete - timecomponent)
		               + " fall:" + makeMsStr(timefall - timedelete)
		               + " crunch:" + makeMsStr(timecrunch - timefall)
		               + " end:" + makeMsStr(timeend- timecrunch),
				Toast.LENGTH_LONG).show();

d'ailleurs si vous connaissez un meilleur moyen d'afficher des infos de debug qu'une Toast ca me ferait plaisir :)

donc, il y a deux grosses méthodes qui prennent le plus de temps : verticalFall et detectEnd.

en fait c'était logique dès le départ, ce sont elles qui font le plus de parcours, en effet elle bouclent sur toute la grille des boutons.

verticalFall permet de faire tomber les boutons vers le bas pour remplir l'espace vidé par la suppression d'un groupe.

detectEnd permet de savoir si il reste des composantes connexes d'au moins deux boutons (4 voisinage) de la meme couleur, dans la grille.

sinon, une bonne nouvelle: en lancant le jeu hors debugger (avec run plutot que debug) on passe de 270ms a 50/60ms. tout a fait acceptable dans mon cas. mais tout de même, ca reste énorme pour aussi peu d'opérations.

je pense que je vais continuer de profiler pour avoir plus de détails, mais j'ai peur de ne trouver que du temps incompressible malheureusement.

voyez plutot:

	End detectEnd()
	{
		boolean empty = true;
		boolean actionable = false;
		for (int y = 0; y < getNumRow(); ++y)
		{
			for (int x = 0; x < getNumCol(); ++x)
			{
				Vector2int pos = new Vector2int(x, y);
				if (!isBtnDeletedAt(pos))
				{
					empty = false;
					Vector<Vector2int> dn = getDirectNeighbors(pos);
					if (!dn.isEmpty())
						actionable = true;
				}
			}
		}
		return empty ? End.EMPTY : (actionable ? End.REMAINS_ACTIONABLE : End.REMAINS_UNACTIONABLE);
	}

	Vector<Vector2int> getDirectNeighbors(Vector2int pos)
	{
		Vector<Vector2int> neigh = new Vector<Vector2int>();
		// probe in 4 directions:
		final int dirx[] = { 0, 1, 0, -1 };
		final int diry[] = { 1, 0, -1, 0 };
		for (int n = 0; n < dirx.length; ++n)
		{
			Vector2int v2 = new Vector2int(pos.x + dirx[n], pos.y + diry[n]);
			if (areOfSameItem(getButtonAt(pos), getButtonAt(v2)))
			{
				neigh.add(v2);
			}
		}
		return neigh;
	}

qu'en dites vous ? vous pensez que ce genre de temps d'execution sont normaux sur un HTC Desire HD, ou alors je fais vraiment les choses n'importe comment ?

Lien vers le commentaire
Partager sur d’autres sites

Je pense que les temps d’exécution sont normaux, car tu crée beaucoup d'objets, et tu utilise beaucoup de Vector.

Je te conseillerai d'essayer d'utiliser dans la mesure du possible les types de base, et les tableaux.

Lien vers le commentaire
Partager sur d’autres sites

Je pense que les temps d’exécution sont normaux, car tu crée beaucoup d'objets, et tu utilise beaucoup de Vector.

Je te conseillerai d'essayer d'utiliser dans la mesure du possible les types de base, et les tableaux.

en effet j'ai trouvé un truc génial : http://developer.android.com/guide/developing/debugging/debugging-tracing.html

j'ai donc fait la trace du programme et ca confirme mes mesures. (pas de bottleneck, tout prend du temps !)

Ca me parait très bizarre quand même parce que y'a bien des jeux assez complexe niveau temps réel sur Android, rien que Angry Birds avec la physique fait plus de calculs que moi et ca tourne en temps réel. y'a un truc qui cloche, y'aurais pas une option de compilation -O2 ou quoi ?

Lien vers le commentaire
Partager sur d’autres sites

Comme je te l'ai déjà dit plus haut, utilise les types de bases, comme les int, les byte, les tableau etc plutôt que des objets évolués comme les vecteurs. Tu devrai tout de suite noter une amélioration significative de tes performances (et accessoirement une consommation moindre de mémoire).

De plus, en règle générale, la récursivité n'est pas ce qu'il y a de plus performant. Mais je n'ai pas vu tout ton code source, donc peux être que pour ton cas, ça l'est.

Enfin, concernant les jeux comme angry birds, je n'ai pas vu leur code source bien sur, mais je suppose que beaucoup de ses calculs sont effectué via le NDK, et probablement via le portage de Box2D vers le NDK.

en effet j'ai trouvé un truc génial : http://developer.android.com/guide/developing/debugging/debugging-tracing.html

j'ai donc fait la trace du programme et ca confirme mes mesures. (pas de bottleneck, tout prend du temps !)

Ca me parait très bizarre quand même parce que y'a bien des jeux assez complexe niveau temps réel sur Android, rien que Angry Birds avec la physique fait plus de calculs que moi et ca tourne en temps réel. y'a un truc qui cloche, y'aurais pas une option de compilation -O2 ou quoi ?

Lien vers le commentaire
Partager sur d’autres sites

Effectivement, ce que tu dis es mentionné la :

http://developer.android.com/guide/practices/design/performance.html

je pleure vraiment quand je lis un truc pareil, on se croirait 20 ans en arrière, faut avoir peur de tout dans ce langage où tout coûte

j'ai effectivement réussi a gagner 20ms (-> passé à 0/1ms sur detectEnd()) en évitant d'allouer les voisins et juste en retournant true ou false, puis en arretant le parcours quand je sais que ca ne sert a rien de continuer.

c'est déjà x2 en perf sur le total des opérations. pour l'instant ca me suffit.

Lien vers le commentaire
Partager sur d’autres sites

C'est assez casse gu***** de comparer un Pc et un téléphone portable.

Même à fréquence égale, les processeurs des Pcs sont des machines très compliquées, qui font beaucoup plus de choses qu'un proc de téléphone, et qui sont donc beaucoup plus efficaces. ( les ARMs sont des RISC, donc qui font des instructions super simples, alors que les Pcs sont des CISC... enfin, je crois que à présent c'est plus compliqué ).

C'est aussi pour ca qu'ils consomment beaucoup moins.

Pour le debuggueur, c'est aussi vrai en c++: brancher un C++ a un impact sur les perfs, mais il est assez faible sur du code natif.

C'est vrai que j'ai été vraiment surpris par l'impact que ca a sur Android.

Apres, le Java est evidemment beaucoup plus lent que le c++, comme tout les langages en bytecode, mais je pense que là, c'est exacerbé par la machine qui est elle meme assez limitée.

La plupart des contraintes qu'ils donnent sont aussi vraies en c++ ( limiter les allocations, se méfier des virtuelles, etc... )

Alocaly / Emmanuel

Lien vers le commentaire
Partager sur d’autres sites

  • 2 weeks later...

d'ailleurs si vous connaissez un meilleur moyen d'afficher des infos de debug qu'une Toast ca me ferait plaisir :)

Salut, oui il y a beaucoup plus simple pour ça. Tu peux utiliser les Log: Ici

De Eclipse tu vas dans Window > showView > Logcat

Voilà ;)

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...