Norswap a écrit :Pas la peine de s'enflammer etc...
@ Norswap
En conclusion moins hâtive, si tu veux contrôler les ressources CPU compatible, ce que j'ai écrit en page 1 (et première "inflammation" ou "ignition", je ne sais pas exactement comment l'exprimer, mais au moins c'est repérable pas la manière dont j'ai présenté l'explication!) est une méthode qui, à mon avis n'a pas d'égal.
Sous XP (ChaOs, Cpl.Bator ou d'autres personnes possédant aussi Linux pourront te renseigner bien mieux que moi pour Linux), au moins sous XP, l'OS apprécie de convention qu'on lui rende la main de manière amiable grâce à l'instruction Delay(n) avec n en milliseconde(s). L'OS étant le "supérieur", c'est lui qui décide quand est-ce qu'il te rend la main. La seule chose est que si toutes les applications en parallèles fonctionnent dans les normes (ce qui n'est pas toujours le cas), et s'il n'y a pas un nombre trop important d'applications en arrière-plan, l'OS te rend la main à intervalles réguliers.
Sans ton application (ou ton jeu), l'OS a toujours la main (signes "-"), et, parce qu'il est conçu ainsi, il nécessite la main de manière irrégulière (signes "X")
Code : Tout sélectionner
-----------|----XXXXXX|----XXXXXX|---------|---------|----> t
t0 t1 t2 t3 t4
Chaque intervalle fait environ 15ms. Je vais appeler cet intervalle le différentiel minimum. Si tu as un doute sur sa valeur, teste le code page 1 (à ce propos j'y reviendrai) sur ton PC pour obtenir éventuellement une autre valeur.
Avec ton application légère en ressource, "O" représente ce que ton application consomme ("D" symbolise d'une part ce qu'elle consomme, d'autre part le fait qu'elle rende la main à l'OS avec l'instruction
Delay).
Code : Tout sélectionner
-----------|OD--XXXXXX|OD--XXXXXX|OD-------|OD-------|OD--> t
t0 t1 t2 t3 t4
Entre t0 et t1, ton application va consommer peut-être 1%, sur un CPU à 1GHz, 0.1% sur un double coeur de 2GHz, etc... Mais l'OS ne te rendra pas la main, comme tu l'as précisé (1ms en argument dans le Delay): il maintiendra son rythme et te le rendra environ 15ms plus tard. Résultat :
l'argument de 1ms dans le Delay() est une durée minimum.
Au fur et à mesure que tu rajoutes des instructions de contrôle et de mise à jour, tes ressources consommées vont augmenter.
Code : Tout sélectionner
-----------|OOOOOOD---|OOD-------|OOOOD----|OOOOD----|D---> t
t0 t1 t2 t3 t4
Maintenant, pour bien comprendre la notion de plantage de jeu (ou d'application), on va garder les proportions (nombres de "O", de "-", etc...) du schéma juste ci-dessus, et on va le mettre dans la plus partageuse des réalités électroniques...
En effet, comme dit ChaOs, ça n'est pas forcément la mer à boire. Ben, il a raison: il ne travaille pas que sous Windows!!
Parce que le Windows qui se chatouille tout seul sans prévenir de temps à autre, ça donne ça:
Code : Tout sélectionner
-----------|OOOOOODXXX|XXX-------|OODXXXXXX|OOOOD-----|D---> t
t0 t1 t2 t3 t4
Et ça, c'est un idéal, car la réalité, c'est que, malgré ce que l'on pense, XP est désormais un OS expérimenté donc il ne plante que très rarement.
Pourquoi? Parce que ses fabricants ont mis une tolérance très large...
Code : Tout sélectionner
-----------|OOOOOOD---|XXXXXX----|---------|XXXXXX-----|OOD-> t
t0 t1 t2 t3 t4
...Et donc évidemment très prenante pour ton application si elle ne respecte pas une consommation maximum...
Code : Tout sélectionner
-----------|OOOOOOO---|XXXXXX----|YYY------|XXXXXX-----|OOOO> t
t0 t1 t2 t3 t4
...Très large donc pour rajouter des protocoles de vérification d'intégrité (signes Y) et parfois...
Code : Tout sélectionner
-----------|OOOOOOD---|XXXXXX----|YYYRR----|YYYRR----|XXXX> t
t0 t1 t2 t3 t4
...que ce soit dans ton application, ou dans une autre, il n'y a plus d'intégrité! Dans ce cas, il y a réparation (signe R), qui comprend une analyse, un annulation respective jusqu'à un retour d'intégrité avec éventuellement une invite pour signifier qu'une erreur est survenue, dans une autre application, etc...
Si, pendant ce temps-là, tu étais train de défoncer Billy The Skeleton à coup de M79, tu n'apprécies pas trop, que l'explosion fatale reste figée, et que Billy ne se retrouve pas au sol, comme tout le monde à l'écran depuis 10 minutes non-stop. De surcroît, tu vas instinctivement rester appuyé sur la détente de ton arme (touche Espace ou autre) pour lui remettre une deuxième mandalle. Résultat: En plus d'une réparation d'un bug qui n'est pas de ton ressort, Windows risque de te dire "Coco tiens-toi tranquille 100ms stp ou je te colle un plantage du bâton de plusieurs secondes!!". Cela n'a bien entendu pas de frontière de compilateur! Pour éviter cette conflictuelle, en PB, un Delay(1) sans condition est obligatoire. (Information généreusement offerte, page 1 par HuitBit)
Et si tu respectes cette douce règle de t'en tenir à environ 2 cycles de l'OS dans tes jeux, comme dans tes applications, (env. 32ms = 30Hertz), l'OS ne t'appellera jamais (ou très rarement) "Coco". Donc deux instructions Delay(1) sont à placer quelque part dans ta boucle principale...(Ou 1 Delay(16) )
Il n'y a rien besoin d'autre pour qu'un jeu ou une application garde la même vitesse générale sur 36 bécanes diverses à 36 vitesses différentes (au moins sur XP) :
60 Hertz environ pour 1 cycles OS (on ne gère pas grand chose + ralentissement à 30 Hz avec risques "Coco" de temps à autres)
30 Hz~ pour 2 cycles OS(on gère pleins de choses + régularité)
20 Hz~ pour 3 cycles OS(saccades visibles)
Avec
1 cycles OS = 1 instruction Delay(1)
2 cycles OS = 2 instructions Delay(1) ou une instruction Delay(16)
3 cycles OS = 3 instructions Delay(1) ou Delay(1)+Delay(16) ou Delay(33)
Remarques:
Un Delay(2) = Delay(1)
Un Delay(3) = Delay(1)
Etc...
On a :
Avec :
Code : Tout sélectionner
Procedure.I F(n.I)
Protected Result.I
Result = 16 + n - n % 16
; Délai réel = 16 + Délai théorique - (Délai théorique modulo 16)
; Résultat précis à + ou - 3%
ProcedureReturn Result
EndProcedure
Donc, pour info, si Tonton a mis un Delay(10) quelque part (je vois ça en lisant le message de Beauregard...), avec toutes mes plus plates et mes plus profondes excuses, ainsi qu'avec mon plus grand respect envers lui comme envers les autres, il s'est planté...
Il a pris en considération que sa boucle principale tournait dans un de ces trois cas:
soit durant 6ms sur 1 cycle OS de ~16ms à ~40% de conso CPU
soit durant 23ms sur 2 cycles OS de ~33ms à ~68% de conso CPU
soit durant 37ms sur 3 cycles OS de ~47ms à ~78% de conso CPU
(je mets les 3 cas parce que je n'ai pas vu son code)
Or, sur mon PC sans doute plus lent que le sien (on va être gentil, on va inventer, on va dire 2 fois plus lent), je pourrais obtenir quelque choses comme:
12ms sur 2 cycles OS de ~33ms à ~37% de conso CPU ; Incompatibilité
46ms sur 3 cycles OS de ~63ms à ~75% de conso CPU ; Incompatibilité
74ms sur 5 cycles OS de ~94ms à ~80% de conso CPU ; Incompatibilité
Dans le premier cas, mon PC exécute 2 fois plus lentement.
Dans le deuxième cas, mon PC exécute 1.5 fois plus lentement.
Dans le troisième cas, mon PC 1.6 fois plus lentement
Pourtant, s'il avait mis "Delay(1)"
J'obtiendrais sur mon PC deux fois plus lent:
12ms sur 1 cycles OS de ~16ms à ~75% de conso CPU ; Compatible
46ms sur 3 cycles OS de ~47ms à ~98% de conso CPU ; Incompatibilité
74ms sur 4 cycles OS de ~80ms à ~94% de conso CPU ; Incompatibilité
Dans le cas où son jeu ne bouffe qu'un cycle par boucle (on va admettre que c'est ce cas de figure pour comprendre les deux autres : on y reviendra), il est compatible avec mon PC puisque, même 2 fois plus lent, il lui faut le même nombre de cycles OS (1 cycle OS, soit une fréquence de 60 Hertz) que sur le sien. Seul inconvénient, mais lui n'y pourra rien a priori : mon PC va bouffer 75% de ressources contre 40% pour le sien.
Alors Tonton (bon, excuse-moi Tonton, j'invente une fiction romanesque pour me faire comprendre correctement par un large public sur cette subtilité technique...), ébahi à l'idée que je puisse bouffer autant de ressources me dit "Ne t'inquiète pas Ollivier, je suis un malin. Je peux bien enlever 2 ou 3 bricoles pour que tu uses de moins de ressources sur ta grosse dau... ton PC un peu plus ancien!"
Moi, gourdin en main de découvrir un jeu aussi puissant fonctionner soudain sur mon PC, j'exclame ma joie : "Merci Tonton ! Youpi! C'est génial !"
Mais là, c'est Tonton qui fait la gueule: sur son PC, le jeu allégé de quelques détails et le Delay() réglé à 1, il fonce beaucoup trop vite et est injouable...
Alors là, magie de la providence, simple hasard, ou bien illumination shadokienne, je n'en sais rien, je lui porte ce conseil à l'oreille:
"Mais Tonton, tu peux peut-être rajouter un deuxième Delay(1) tous les x boucles, et ce "x", tu le calcules en début de jeu, avant la boucle principale!"
Résultat des courses : Tonton est content sur son 2GHz, et moi je suis content sur ma grosse daube.
Fin de l'histoire.
Petit apparte concernant les critiques susceptibles de naître quand à mon bon conseil de prôner une gestion à 30 Hertz (2 cycles OS) plutôt qu'à 60 Hertz (1 cycle OS), les gens qui, bien évidemment souhaiterait me prouver (par du code, cela va de soi) que j'ai tort peuvent toujours essayer : avant qu'ils perdent du temps à, je le répète essayer de prouver que j'ai tort (de ne jamais travailler à plus de 30 Hertz) (Pour qu'ils m'évitent de perdre moi-même du temps à devoir leur répondre par un code qui leur montre qu'ils ont tort définitivement), qu'ils comprennent juste ma douleur d'être à ce point aveugle :
- Quand je me prends des baffes en pleine tronche à 25 Hertz, je les sens toutes, sans exception, cependant, même les yeux ouverts et le plus sobrement du monde, je n'en vois aucune, ni arriver, ni repartir, et cela, bien évidemment sans exception : Persistence rétinienne oblige, le reste n'est que marketing matériel déviant tranquillement mais bêtement vers les logiciels. J'espère que cette compassion suffira.
Concernant le différentiel minimum, les fameuses 15 (ou 14, ou 16 ms) millisecondes que j'évoque tout au long de ce tutoriel, j'ai fait un code tout bête pour le mesurer donc page 1.
Je peux le remettre là même, ça ressemble à ça:
Code : Tout sélectionner
Depart = ElapsedMilliseconds()
Delay(1)
Fin = ElapsedMilliseconds()
Debug Fin - Depart
Alors, ta réflexion "Ne t'enflamme pas, ils veulent aider, etc..."... Mh... Je la connais quand même la bande à Basile: vu qu'il y en a aucun qui m'a posté "Oh! Beuh... ouais! Sur mon PC j'ai aussi 15ms! Tiens... Donc pas besoin de se souler à faire ci et ça, etc...", voire (là, c'est de l'ordre du fantasme chronico-utopique) "Génial!", ou autre, moi je n'ai aucun doute sur leur plus grande motivation à plutôt vouloir se poiler la gueule, quite à ce que toi, tu n'avances pas de suite sur cette question précise de perf (et donc de compatibilité "multi vitesse"), et juste pour dire qu'ils en ont rien à foutre de casser du processeur depuis des années!!". Ils m'en apprennent tous les jours, je leur en apprends aussi de temps en temps : c'est ça aussi la magie d'un forum. Si on ne peut plus mettre à poil les gens qui te mettent à poil, où serait le plaisir!?! Maintenant, à cause de ce sujet, j'espère bien que 95% des gens qui vont réussir à le lire entièrement vont mettre à jour leur noyau (boucle principale), comme ça je pourrais peut-être enfin exécuter un tout petit peu plus de sources "open" sans en avoir à faire la recherche de la boucle principale, galérer en me disant "encore un punaise de punaise de bourrin..." et puis renoncer.
Alors, je t'explique le mode d'emploi du cas Ollivier.
1) Sélectionner son code publié dans le forum (il n'y a qu'ici) sans en oublier ni la première, ni la dernière ligne
2) Appuyer sur Ctrl-C
3) Retourner dans ton éditeur
4) Cliquer sur "Nouveau" dans l'éditeur, puis cliquez sur la feuille
5) Appuyer sur Ctrl-V
6) Appuyer sur F5
Tu vois, cette règle est valable pour un de mes codes de 4 lignes comme de 40, 400 ou 4000 lignes. Elle est valable, aujourd'hui comme demain, dans un an, dans dix ans, et tout cela si le Ciel le veut. Mais il n'y aura jamais plus compliqué à attraper pour que le fruit s'affiche à ton écran.
Si tu comprends cela, tu as tout compris du cas Ollivier. Simple (là, devant ce mot, tu en as au moins 10 qui se marrent...)
Alors toi, fais-moi plaisir, au lieu de me couler gaiement et surtout, inutilement, teste les codes que je poste: au moins le tout dernier!!! Celui-là, juste ci-dessus ne fait pas 25000 lignes!! C'est un minimum de le tester et de donner un réponse qui puisse être commentée: quel nombre vois-tu s'afficher ?