Bonjour,
Je vous propose un petit troll du Vendredi, ainsi qu'un défi.
J'utilise Java Sound pour enregistrer et jouer du son. J'avais, avec le JDK 1.3 des problèmes de pertes de synchro, i.e. Java arrivait pas à suivre la cadence. Les marketteux de chez Sun prétendant que Java Sound était maintenant en Direct Sound (pas celui de M$, celui de Java) depuis la 1.4, utilisant Alsa ou bien DirectX, marchait beaucoup mieux.
Le problème c'est que Java, c'est peut-être plus rapide que C++, mais ça ne sait pas scheduler un thread correctement.
En effet, ma carte son me donne un buffer d'enregistrement de 1s au max (avec Direct Sound on ne peut pas choisir la taille du buffer, et maintenant Sun ne donne plus accès au Java Audio Engine pour l'enregistrement). Du coup, il faut que mon thread d'enregistrement soit schédulé au moins une fois par seconde.
Et ben cette merde de Scheduler qu'il y'a dans la JDK, il est pas capable de me faire ça. A peu près toutes les 30s, mon thread n'est pas schédulé à temps. Pourtant je lui demande un scheduling toutes les 100ms via un wait(100) dans mon thread. Et ce, sans que rien ne tourne en tâche de fond, sauf les processus de mon OS et les quelques threads "system" de la JVM.
Sur un Pentium IV 2.4GHz avec 1 Go de RAM, 0% d'utilisation CPU, le scheduler de la JVM n'est pas foutu de faire en sorte que mon thread soit schedulé avant 1s.
Du coup, le son en Java on peut oublier :)
Je vais coder un bout de C++ pour gérer ça et passer par JNI.
Conclusion la terre est plate (c.f. la page performance sur jsresources.org).
# Je prends les paris
Posté par Wawet76 . Évalué à 10.
[^] # Re: Je prends les paris
Posté par iug . Évalué à 6.
[^] # Re: Je prends les paris
Posté par gc (site web personnel) . Évalué à 5.
[^] # Re: Je prends les paris
Posté par iug . Évalué à 1.
[^] # Re: Je prends les paris
Posté par Nelis (site web personnel) . Évalué à 2.
Sinon c'est comme si je disais : le C sous Linux c'est pas bien parce que mon thread se désynchronise, alors que j'ai surement un gros bug dans mon code ...
[^] # Re: Je prends les paris
Posté par iug . Évalué à 2.
_in est une TargetDataLine en Java Direct Sound,
_bigBuf, c'est un plus gros buffer circulaire dans lequel je mets mes données, et que le player va lire pour les jouer sur la carte son par exemple (on va supposer qu'il marche...) (même quand seul le recorder est seul, sans player, j'ai le problème, bon ok, j'ai pas essayé sans la copie vers le bigBuf)
le corps du run() est :
while (started) {
size = _in.available(); // récupère la taille des données dispo
_in.read(buf, 0, size); // récupère les données (une copie //supplémentaire, je sais)
_bigBuf.put(buf, 0, size); // écrit dans le buffer circulaire
Thread.wait(100); // Attends au moins 100ms, si possible moins de 1s
}
Ca ne vous avance pas à grand chose. Sinon, y'a des sorties textes de debug au milieu de tout ça, ce qui peut expliquer la chose. M'enfin, je suis plus au taf, donc je peux pas essayer.
Merci pour la proposition, mais ça vous avance à rien. Y'a pas de deadlock vu que seul un consommateur tourne :) Si mon buffer circulaire buggait, j'aurais des excpetions. Vu qu'il ne fait pas 1Mo ça n'explique de toute façon pas la latence, une copie de 1Mo prenant moins d'une seconde. Une copie de plus de 1Mo déclencherais une excpetion...
[^] # Pfff
Posté par bobert . Évalué à 0.
En fait, ça n'avance même à rien, vu que tu donnes un code incomplet.
Quel est le type de _in ? InputStream ? BufferedInputStream ?
Quel est le type de buf ? Où est le code de _bigBuf ? Que fait sa méthode put ?
Évidemment en nous montrant 3 lignes tronquées de ton code ça fait pas du tout avancer le schmilblik, à croire que tu fais exprès, ça doit faire partie de ton troll.
Tout ce que ça montre, c'est que tu es plus habitué à c++ qu'à java, parce que préfixer d'un '_' le nom des attributs privés est un idiome c++ ; en java, on se contente du modifiant private.
[^] # Re: Pfff
Posté par Troy McClure (site web personnel) . Évalué à -3.
Naon, en c++ comme en c, les identifieurs commençant par un underscore sont reservés pour l'usage interne du compilo et de la bibliothèque standard !
[^] # Re: Pfff
Posté par Matthieu Moy (site web personnel) . Évalué à 3.
Bien relire le message du môsieur ...
[^] # Re: Pfff
Posté par iug . Évalué à 2.
Et en mettant des currentTimeMillis() partout, j'ai vu que mon appel à _in.read() avec comme dernier paramètre le résultat renvoyé par _in.available(), qui ne devrait donc pas bloquer, prend la plupart de temps à peu près 0 ms et de temps à autre 1000ms, comme si il bloquait pour attendre un remplissage complet du buffer interne de la carte son, qui dur 1000ms.
Le scheduler n'est pas en cause, ni ma synchro, le wait() du thread dure grosso modo ce qu'il faut. D'ailleurs, chose bizarre, il dure parfois moins que le temps demandé.
Je vais essayer de creuser le problème. Par exemple ma carte est une fausse full duplex.
[^] # Re: Pfff
Posté par iug . Évalué à 5.
Je sais pas si c'est dû au driver de ma carte son, à DirectX, ou au JDK mais maintenant que je lis 1000 octets de moins que ce que me donne le available() et ben jai plus de read() bloquant.
Toutes mes excuses pour les critiques du scheduler, qui n'était pas en cause, de même que le GC.
[^] # Re: Je prends les paris
Posté par Sylvain Sauvage . Évalué à 4.
C'est tout.
Java n'est pas temps réel (ton OS non plus, je pense), il ne promet pas que le retour se fera avant un délai donné (il peut très bien finir dans 25 ans).
Ton problème vient peut-être des entrées-sorties ou du garbage collector qui viennent perturber l'ordonnanceur.
Ensuite, ce n'est parce que tu vas passer par du JNI que la machine virtuelle ou les entrées-sorties ne vont pas continuer à venir perturber le fonctionnement de ton prog.
Sans parler des problèmes que l'on peut avoir en mélangeant les threads natifs aux threads Java.
Enfin, si tu n'as aucun raison pour faire un Thread.wait(100) plutôt qu'un Thread.wait(10), autant faire un Thread.yield(). De cette façon, ton thread reprendra la main dès que possible.
[^] # Bien tenté...
Posté par bobert . Évalué à 7.
Bien tenté, mais dans la pratique ça fonctionne en sens inverse: c'est à toi de nous montrer ton code pour démontrer ta compétence.
[^] # Re: Je prends les paris
Posté par iug . Évalué à 2.
Si tu fais juste un petit programme "cas décole" qui ne fait aucun traitement et se contente de faires des println dans la console à chaque production et consommation, tu observeras des pauses assez fréquentes.
Ce qui me fait halluciner c'est que ces pauses peuvent durer plus d'une seconde.
Je me demande si ce sontles programmeurs qui ont implémentés le truc qui sont incompétents ou bien, pire, si c'est une faille de la spec d'implémentation des API de thread qu'ils ont en interne chez Sun.
Quand on voit la qualité de Solaris, on se dit qu'ils pourraient débaucher quelques hackers pour les mettre à bosser sur Java.
[^] # Re: Je prends les paris
Posté par Nelis (site web personnel) . Évalué à 3.
Peut-être peux-tu nous montrer ton code ?
[^] # Re: Je prends les paris
Posté par Mathieu CLAUDEL (site web personnel) . Évalué à 5.
peut etre le garbage colector qui tourne
</neophite>
[^] # Re: Je prends les paris
Posté par lolop (site web personnel) . Évalué à 1.
(y'avait un article là-dessus dans un numéro de GNU-Linux Magazine)
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Je prends les paris
Posté par Tobu . Évalué à 1.
[^] # Re: Je prends les paris
Posté par Krunch (site web personnel) . Évalué à 2.
pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.
[^] # Re: Je prends les paris
Posté par Tobu . Évalué à 2.
En même temps le journal parlait du Java 1.4 de SUN avec ses API très complètes.
[^] # Re: Je prends les paris
Posté par gc (site web personnel) . Évalué à 2.
Je te suggère aussi de lire ce qui suit :
http://www.armadilloaerospace.com/n.x/johnc/recent%20updates/archiv(...)
[^] # Re: Je prends les paris
Posté par Thomas Hervé . Évalué à 4.
Au cours de tests d'applis Web sous Tomcat, j'ai utilisé un outil pas mal qui s'appelle Jprobe profiler (ca pue c'est pas libre). Pour constater que les latences de mon application étaient dues aux allocations mémoire. En gros quand la JVM augmente (ou diminue) la mémoire disponible, elle ne peut rien faire d'autre ou quasiment... Sachant qu'une application Java est assez consommatrice de mémoire, j'avais des pauses toutes les 10 secondes.
--
Thomas <et voilà que je me met à donner des conseils Java. Tout fout le camp>
[^] # Re: Je prends les paris
Posté par kesako . Évalué à 3.
[^] # Re: Je prends les paris
Posté par romain . Évalué à 1.
[^] # Re: Je prends les paris
Posté par lolop (site web personnel) . Évalué à 3.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Je prends les paris
Posté par Fanf (site web personnel) . Évalué à 0.
Heu... LE Thomas que je connais ? En effet, tout fou le camp :)
[^] # Re: Je prends les paris
Posté par romain . Évalué à 3.
Il me semble, si je me souviens bien mes cours de temps réel (en Java, vivi), qu'il y a au moins deux modèles (green box, native ou standard, je ne sais plus) et que cela peut avoir une incidence sur le scheduling des threads et leurs synchro (pas de pointeur en tête, désolé).
[^] # Re: Je prends les paris
Posté par iug . Évalué à 1.
En tout cas, question RT, effectivement Java ne donne pas plus de garantie que Linux vanilla ou Windows en matière de schéduling. Par contre dans ces deux derniers cas, dans la pratique, on n'a pas de latence de 1s.
Question pause, et ben oui elles y sont. Et effectivement, je me suis démerder pour ne plus faire d'alloc dans ma boucle de pompage, et les pauses y sont encore.
[^] # Re: Je prends les paris
Posté par Mobaladje . Évalué à 2.
"A peu près toutes les 30s, mon thread n'est pas schédulé à temps."
Ca veut dire quoi exactement ?
Le wait ne se fait pas ? (très improbable).
Les waits n'étant pas "constants", tu as une attente plus longue (ou plus courte) au bout d'un certain temps ? (plus probable).
Que veux tu faire exactement ?
[^] # Re: Je prends les paris
Posté par Tobu . Évalué à 2.
D'ou bizarrerie: le thread n'est censé ne dormir que 100ms.
[^] # Re: Je prends les paris
Posté par jigso . Évalué à 3.
[^] # Re: Je prends les paris
Posté par Nicolas Bernard (site web personnel) . Évalué à 0.
Je crois que les hackers en question préfereraient démissioner que de travailler sur Java...
# J'ai pas constaté.
Posté par locnet . Évalué à -3.
Je ne constate pas des pauses d'une seconde périodiques.
Ton problème n'est probablement pas généralisé à tout java. Reste a trouver ce qui le déclenche.
[^] # Re: J'ai pas constaté.
Posté par TImaniac (site web personnel) . Évalué à 0.
Non sérieux, c'est bien connu, Eclipse il ralenti jamais, surtout quand le GC passe dans le coin, y'a jamais plus de 2 µs entre le click de la souris et la réaction de l'IHM, c'est bien connu, surtout au bout de 3h d'utilisation, sous Linux s'il vous plaît...
Bon allez j'ai assez ri, hop -->[]
# vu sur le site de SUN
Posté par Christophe Martel . Évalué à 9.
exemple de thread schedulé :
http://forum.java.sun.com/thread.jspa?forumID=45&threadID=24306(...)
Help with JMF Synchronisation :
http://forum.java.sun.com/thread.jspa?forumID=28&threadID=52346(...)
tutorial:
http://java.sun.com/docs/books/tutorial/essential/threads/priority.(...)
doc :
Capturing Time-Based Media with JMF :
http://java.sun.com/products/java-media/jmf/2.1.1/guide/JMFCapturin(...)
# javasound
Posté par vrm (site web personnel) . Évalué à 1.
[^] # Re: javasound
Posté par iug . Évalué à 5.
[^] # Re: javasound
Posté par vrm (site web personnel) . Évalué à -1.
# une "solution"
Posté par kra . Évalué à 4.
ca correspond plus a ce que tu veux faire visiblement (ie : executer une tache toutes les n ms plutot que d'executer une tache en continue qui dort 90% du temps)
[^] # Re: une "solution"
Posté par iug . Évalué à 2.
# \o/
Posté par kassoulet (site web personnel) . Évalué à -3.
c'est une blague j'espere :)
# Lâcher de trolls
Posté par Obsidian . Évalué à -2.
Tu te prends pour Pierre Tramo ?
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.