1

Pas vraiment un outil, mais j'en avais besoin, et ça a fini en package NuGet. (Et premier non-vap0rware!)

DBFilesClient.NET est une lib C# capable de lire les fichiers DBC et DB2 extraits des archives de jeu de World of Warcraft.

L'intérêt? J'ai pu apprendre à utiliser Reflection.Emit, et surtout me débarasser de mon vieux code qui fonctionnait à fond sous Reflection. Et puis en plus passer à Emit a multiplié la vitesse d'exécution d'un facteur 10.

Du coup je balance ça si y en a ici qui tripotent un peu wow (je sais que c'est ou c'était le cas de GC):

https://github.com/Warpten/DBFilesClient.NET

Le package NuGet du même nom est sur le tag 1.0.0.1

2

J'ai arrêté de "tripoter" WoW depuis longtemps, mais j'avais déjà un truc comme ça à l'époque: https://github.com/GoldenCrystal/CrystalMpq/blob/master/CrystalMpq/CrystalMpq.DataFormats/ClientDatabase.cs#L435 cheeky
(Par contre je n'ai jamais accédé à ces nouveaux formats à la mode, juste aux anciens, vieux DBC)

Sinon, dans ton code, tu devrais essayer de bosser plus par composition que par héritage: tu hérites de BinaryReader, mais la plupart de tes méthodes pourraient se trouver dans une classe statique (par exemple sous forme de méthodes d'extension) et fonctionneraient aussi bien.
De la même manière, tes reader finaux n'ont pas besoin d'instance (en dehors d'une référence au BinaryReader) et tu pourrais les implémenter comme méthodes statiques quelque part.

Bravo, en tout cas wink
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

3

GoldenCrystal (./2) :
Sinon, dans ton code, tu devrais essayer de bosser plus par composition que par héritage: tu hérites de BinaryReader, mais la plupart de tes méthodes pourraient se trouver dans une classe statique (par exemple sous forme de méthodes d'extension) et fonctionneraient aussi bien.

Le problème des méthodes d'extension c'est que ça reste du syntaxic sugar, donc pour l'invocation ça rajoute simplement un paramètre en plus:

typeof(Extensions).GetMethod("...", new[] { typeof(Reader), ... })
C'était juste moins chiant de dériver de BinaryReader et de partir de là grin
GoldenCrystal (./2) :
De la même manière, tes reader finaux n'ont pas besoin d'instance (en dehors d'une référence au BinaryReader) et tu pourrais les implémenter comme méthodes statiques quelque part.

Yep, c'est prévu, mais j'ai déjà rollout une mise à jour qui "casse" le fonctionnement de la première release pour les WDB5 dans la plupart des cas, donc je préfère stabiliser la lib avant de la mettre à jour.

Je voudrais aussi me débarasser de Sigil, mais pour une raison quelconque je finis par me taper des exceptions internes dans les fonctions émises au bout d'un certain moment (ça charge N entrées puis bim, exception, et c'est pas spécialement évident de déboguer ces exceptions puisque la véritable est "cachée", le JIT pensant que c'est une erreur dans le BCL ..) Quand j'utilise Sigil, ça fonctionne, et pour avoir comparé l'IL sorti, je ne vois aucune différence à part la granularité normale pour de l'IL.

4

Pour ton cas qui foire, tu as observé des données en particulier qui produiraient ce souci, ou bien c'est vraiment dans tous les cas ? Car il y a peut être un cas où tu gères mal une valeur de retour, ou un truc du genre, qui ne se verrait pratiquement pas.

Sinon, tu n'es pas obligé d'utilsier Sigil (même si ça marche très bien) ou Reflection.Emit pour générer du code, tu peux aussi utiliser System.Linq.Expressions dans pas mal de cas. (Cet API a certaines limites, et est sans aucun doute plus coûteux en mémoire et en performances à la compilation, mais pour du CodeGen basique, ça peut simplifier la vie ^^)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

5

J'avais effectivement regardé du côté d'Expressions, ça sera sûrement pour une prochaine version, ou même si un jour je me met au F# et autres variantes ^^.
Pour ton cas qui foire, tu as observé des données en particulier qui produiraient ce souci, ou bien c'est vraiment dans tous les cas ? Car il y a peut être un cas où tu gères mal une valeur de retour, ou un truc du genre, qui ne se verrait pratiquement pas.

Au début je pensais que pour une raison quelconque ça se foirait sur la lecteur de chaîne de caractères, du coup j'ai écrit plein de variations de ma fonction, ce qui n'a eu pour effet que de déplacer le site de l'exception du JIT... Je n'ai pas regardé plus loin que ça. J'ai aussi regardé la directive .maxstack, mais on ne peut de toute façon pas la forcer...

En revanche pour chaque fichier, pour chaque version de la DLL, ça se foirait exactement au même endroit. (Mais pas pareil entre deux fichiers!). Et pour certains fichiers tout fonctionnait bien (sans savoir si c'était à cause du faible nombre d'entrées, ou de la taille des entrées, ou de la présence ou l'absence de chaînes de caractères)

J'ai eu l'idée que c'était peut-être un problème lié au garbage collector, mais j'ai pas creusé plus loin, ça me semblait tiré par les cheveux

6

Nan mais c'est forcément un bug dans ton programme… Le JIT peut avoir des bugs (c'est arrivé dans le passé, c'est certainement encore le cas aujourd'hui) mais c'est rarement simple, vu que la majorité des fonctions sont utilisées par les développeurs (et par extension leurs utilisateurs) quotidiennement.

Ce que tu peux faire pour déboguer ça c'est de générer un assembly "RunAndSave" au lieu d'une DynamicMethod (c'est un peu plus de code, que tu supprimeras une fois ton boulot de correction fini, mais c'est la meilleure façon de faire)
Du coup, tu dois pouvoir aussi y générer des infos de débogage, ce qui peut (ou pas aider) à voir ce qui se passe dans Visual Studio. (Eventuellement…)
Mais surtout, ça va te permettre de passer ton code à peverify.exe qui détecte bien plus de choses que le runtime. (Le runtime fait beaucoup de vérifications, mais il va en sauter quelques unes non essentielles, et puis même si il ne les saute pas, il ne te dira pas toujours précisément ce qui ne va pas)
En parallèle de ça, je t'encourage fortement à passer ta DLL générée dans un décompilateur C# (Oui, ces choses ont une vraie utilité parfaitement légale tongue) comme ILSpy, vu que ça doit être le meilleur gratuit du moment. L'idée c'est qu'il doit arriver à comprendre ton code IL*, et à te ressortir l'algorithme que tu as implémenté sous forme de C#: ça te permettra de vérifier d'un rapide coup d'œil que tout se fait exactement comme tu le voulais. smile

* Attention, ILSpy peut aussi se foirer dans certains cas, ce n'est pas un vérificateur IL.
Bugs de décompilation

J'ai quelques exemples en tête où ILSpy/autres se foire à la décompilation, mais ce n'est pas exhaustif smile

Ceux où il ne décompile "pas assez" sont nombreux, mais rarement très graves, vu que ça n'impacte pas la logique du code:
  • Mélanger async et dynamic dans la même méthode, ça peut vite paumer la décompilation. (Ce sont deux domaines qui provoquent une réécriture de code massive de la part du compilateur C#, chacun à leur façon)
  • Faire des switch avec trop de cas possibles (ça a peut être été corrigé depuis, ça fait très longtemps que je l'ai constaté)
  • De manière générale, toutes les structures de code un peu trop complexes risquent de faire apparaître des goto au lieu de l'enchevêtrement de structures natives. (Mais c'est logique, vu que tout est basé sut goto à la fin)

Par contre c'est l'algorithme de simplification du code qui peut se foirer légèrement ou lourdement. (Donc, à l'inverse des cas où il n'en fait pas assez)
Parfois, des détails vont carrément disparaître du code décompilé, produisant soit du code qui ne compile pas, soit du code qui ne correspond pas à l'original.
  • En C# l'opérateur ternaire est vraiment chiant, car totalement inflexible au niveau de la détermination de type: souvent on est obligé de caster une ou l'autre des deux branches vers le bon type pour que le code compile. Mais des fois, ce cast saute à la décompilation. (Typiquement dans les cas où le cast va disparaitre en IL parce qu'il servait réellement à rien, et ces cas sont assez nombreux)
  • Des cas où le code est un peu tordu car codé plus en IL qu'en C# et où le décompialteur va interpréter un bout de code comme un autre pattern à tort. (Typiquement, le compilateur C# ne produit pas un code IL efficace. "Pas" ne veut pas dire "jamais", mais il y a plein d'optimisations impossibles à faire par le JIT que le compilateur C# ne fait pas, alors qu'il pourrait les faire, et plein d'optimisations que le JIT sait faire et que le compilateur C# ne s'embête pas à faire, et qui génère un IL plus gros que nécessaire. Le code IL généré à la main ne possède pas nécessairement ces mêmes défauts, mais ne rentre de fait pas dans les mêmes stéréotypes que le code C#)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

7

GoldenCrystal (./6) :
il y a plein d'optimisations impossibles à faire par le JIT que le compilateur C# ne fait pas, alors qu'il pourrait les faire
Par curiosité tu as des exemples en tête ?
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

8

GoldenCrystal (./6) :
Ce que tu peux faire pour déboguer ça c'est de générer un assembly "RunAndSave" au lieu d'une DynamicMethod (c'est un peu plus de code, que tu supprimeras une fois ton boulot de correction fini, mais c'est la meilleure façon de faire)
Du coup, tu dois pouvoir aussi y générer des infos de débogage, ce qui peut (ou pas aider) à voir ce qui se passe dans Visual Studio. (Eventuellement…)
Mais surtout, ça va te permettre de passer ton code à peverify.exe qui détecte bien plus de choses que le runtime. (Le runtime fait beaucoup de vérifications, mais il va en sauter quelques unes non essentielles, et puis même si il ne les saute pas, il ne te dira pas toujours précisément ce qui ne va pas)
En parallèle de ça, je t'encourage fortement à passer ta DLL générée dans un décompilateur C# (Oui, ces choses ont une vraie utilité parfaitement légale tongue) comme ILSpy, vu que ça doit être le meilleur gratuit du moment. L'idée c'est qu'il doit arriver à comprendre ton code IL*, et à te ressortir l'algorithme que tu as implémenté sous forme de C#: ça te permettra de vérifier d'un rapide coup d'œil que tout se fait exactement comme tu le voulais. smile

C'est ce que j'avais fait pour Item-sparse.db2, je dois encore avoir la DLL, et tout semblait correct. Par contre, peverify ne voulait juste pas voir la méthode ("... is not visible", alors que c'était une public static), j'avais pas cherché plus loin.

9

Une "bizarrerie" que j'ai remarqué.

Quand tu construis une condition de boucle for, typiquement i < n, tu écris ceci:
for (...; i < n; ...)

ça se compile (en tout cas chez moi) en quelque chose comme ça:

ldloc.0      ; Charge i sur la pile
ldloc.1      ; Charge n sur la pile
clt          ; Compare less than; pop i et n et push le résultat sur la pile
stloc.2      ; Stock le résultat dans une local, pop la pile
ldloc.2      ; Push le résultat sur la pile
brtrue.s ... ; pop l'entier à index 0 sur la pile : s'il vaut 1, branch, sinon continue 

On voit immédiatement que

stloc.2
ldloc.2

est redondant, puisque clt pousse déjà le résultat de la comparaison sur la pile.

10

À tout hasard, ça serait pas du code de debug qui t'a généré ça ? ^^
Sinon, ce genre de trucs (les locales inutiles) c'est la classe

./8 > DynamicMethod peut sauter les vérifications de visibilité (c'est une fonctionnalité, c'est bien pratique), mais dans ton cas tu n'en a pas besoin, donc ce type de message ne devrait pas apparaître
Ton code généré ne doit générer aucun message à la moulinette peverify. Sinon, c'est que le code généré est mauvais, et ça peut expliquer des bugs étrange. (Ou pas)
Si tu sais retrouver le message d'erreur exact et le bout de code incriminé, je veux bien y jeter un œil ^^

Zeph > Typiquement, tout ce qui est du code haut niveau, où le compilateur fait un vrai boulot, est un territoire problématique. C'est là où on sort du domaine "Le CLR supporte les fonctionnalités abstraites de tous les langages" pour aller dans le domaine du "Le CLR ne permet pas de faire X nativement, mais on peut construire X avec les blocs fournis par le CLR". (Un peu comme on peut créer le CLR avec de l'assembleur x86… ça ne permet pas pour autant au CPU de comprendre ce qu'est un objet ^^)
La majorité des fonctionnalités de C#2.0* jusqu'à C#5.0** ne sont pas gérées par le CLR. Le CLR ne sait pas ce qu'est une expression lambda, n'a pas la moindre idée de ce qu'est une méthode d'extension, ignore complètement l’existence de méthodes asynchrones, etc. Tout ça, c'est problématique, parce que la promesse initiale qui disait "Le compilateur C# n'a pas besoin d'optimiser trop fort, car on peut faire ce travail au niveau du JIT et ça bénéficiera à tous les langages", ne vaut plus un clou dans ce contexte.
Si tu veux optimiser les méthodes async, les énumérateurs, les closures, ou que sais-je, tu dois d'abord décompiler le code, pour l'exprimer sous une forme avec laquelle tu pourrais travailler, puis ensuite le recompiler comme il faut. C'est un travail trop énorme pour un JIT, et en plus il n'y a pas de façon de faire standard. (Le compilateur implémente ses structures comme il veut.)

* C# 2.0 a apporté les closures avec la syntaxe "delegate {}" et les itérateurs. Par contre, la majorité de ses apports était lié à un gros ravalement de CLR et du JIT.
** C# 6.0 ne fait qu'ajouter du sucre syntaxique fort attendu ou exposer des fonctions natives du CLR, et tranche massivement avec ses 3 prédécesseurs. (Mais il y a Roslyn !)
Parlons des delegate

J'irai vérifier que c'est encore le cas à l'occasion, mais l'exemple qui me reste toujours en mémoire, c'est que dans l'utilisation des lambda, le compilateur C# va générer des closures inutiles, ou même des méthodes inutiles dans des cas où il pourrait faire sans. (une closure c'est deux allocations d'objet: une allocation pour l'instance, et une allocation pour le delegate)

Tout ça tient au fait qu'un delegate soit un pointeur de méthode, donc contienne une référence d'objet plus une référence de fonction et que le paramètre implicite d'instance this ne soit en réalité qu'un paramètre de méthode comme les autres.

Théoriquement, tu peux transformer une méthode statique de signature Func<A, B> en Func<B>, si A est de type référence.
Pratiquement, le compilateur t'autorise même à le faire toi-même via les méthodes d'extension: dans le contexte d'une création de delegate "reference.ExtensionMethod" va te créer un delegate dont la méthode est "ExtensionMethod" et l'objet "this" est "reference".

Théoriquement, si tu as besoin d'un Func<A, B> mais que tu n'as qu'une méthode d'instance "class A { B F() => default(B); }", tu peux avoir un delegate Func<A,B> directement, qui pointera "statiquement" sur la méthode "A.F".
En pratique, tu peux le faire, mais il n'existe aucun moyen au niveau du langage C# de faire ainsi. En C#, tu pourra faire une lambda "a => A.F()", mais ça va te générer une méthode (complètement inutile) de plus dans le code. Par contre, choppe la référence de méthode "A.F" et construis le delegate Func<A, B> à la main, et ça fonctionnera.

(Une variation de ça, c'est si un type d'objet A possède une propriété de type B, le getter est déjà une méthode qui peut être utilisée pour faire un delegate Func<A,B> ou Func<B> selon ce qui est désiré)

Je suis pas inspiré aujourd'hui donc j'ai pas de bon exemple de code sous la main, mais ce sont des trucs un peu couillons, car ça serait très facile pour le compilateur de détecter qu'il n'a pas besoin de créer une classe et/ou une méthode dans le cas de certains delegate. C'est d'autant plus bête que dans certains cas (je ne connais pas l'algorithme de décision) le compilateur s'embette à mettre en cache les instances de delegate. Combiné avec les optimisations qui ne sont pas faites aujourd'hui, tu pourrais passer de "n" allocations, voire "2n" allocations à une seule et unique allocation.
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

11

Bon ça reste très théorique, tout l'intérêt d'avoir un IL intermédiaire est effectivement de supprimer le sucre syntaxique de l'équation (async, delegates, etc.) donc rien d'inattendu jusqu'ici. Je serais curieux de voir quel type d'optimisation aurait pu faire le compilo au niveau C# et qui devient impossible en IL, j'imagine qu'il en existe mais est-ce qu'il y a vraiment des cas où le gain n'est pas anecdotique ? Je n'ai pas d'exemple en tête smile
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

12

GoldenCrystal (./10) :
À tout hasard, ça serait pas du code de debug qui t'a généré ça ? ^^

Possible, mais je ne vois pas en quoi ça aide... C'est une locale qui n'existe pas dans le code "de base", donc je n'y ai pas accès à moins d'aller lire directement dans la pile ...

13

./11 > Bah en gros justement, le problème que j'exprime c'est que dans le combo C#/CLR actuel, async et lambdas soient du "sucre syntaxique", si on peut apeller ça comme ça pour une fonctionnalité si grosse: En pratique, le code généré par la réécriture en state machine est juste impossible à faire par un humain lambda. (On peut concevoir le système une fois, on peut le comprendre, donc le généraliser (ce qui a été fait), mais on peut pas le faire manuellement à chaque fois).

Aujourd'hui, si tu écris une une méthode A qui ne fait qu'apeller une méthode B avec certains paramètres, le JIT en aura connaissance, et va inliner ton appel de méthode. Maintenant, si tu procèdes de même avec une méthode async, ça ne va pas être aussi simple. Rien que le fait que le code généré contienne un try/catch va causer de gros problèmes: on n'a en théorie "pas le droit" d'optimiser ce genre de choses car ça rend le stack trace erroné, même si dans ce cas, ça n'a aucune importance. Au final, tu vas te retrouver à créer deux belles grosses machines à états, quand une seule t'aurait suffi. (Déjà ça produit un overhead au niveau du code généré, significativement plus lourd, mais ça aura un impact au runtime non négligeable si le code est utilisé souvent)

Pour l'histoire des delegate donc je parlais, c'est un truc plus con, mais tu dis au JIT de créer un delegate, il va créer un objet (il ne peut en théorie pas avoir de connaissance absolue sur l'objet qu'il va créer), et si tu crées ton delegate sur un objet "closure" que le compilateur C# a décidé de créer bien qu'il eut pu faire sans, ben le JIT n'aura pas la capacité de le détecter. Y'a un moment où tu as perdu l'information vitale (que la closure servait à rien), et l'information a été perdue dans le compilateur C#.

C'est pas vraiment théorique et anectodique: Si tout le monde écrit du code qui génère ce genre de comportements (après tout, ouais, c'est "pas très grave"), bah au niveau du monde entier, tu as consommé n*x cycles CPU en trop chaque minutes, et tu as dépensés je ne sais combien de kWh à cause de ce phénomène. Et crois moi, on génère tous ce genre de code à un moment où un autre où on ne fait pas attention. (Je l'ai vu faire chez mes collègues, je l'ai lu dans des codes sur internet, je suis tombé dans le truc plusieurs fois. Et c'est vraiment con, parce que c'est le genre de trucs où tu ne devrais pas te poser de questions: la façon "simple" dont tu écris ton code ne devrait rien changer… Mais ça change.)

C'est le même principe que d'écrire du code pas forcément trop optimisé dans ton programme. En soi, ça gêne pas s'il n'y a pas de problèmes de performances. Mais si tu fais une lib, destinée à être utilisée par d'autres, ça gêne toujours. C'est simple: ton code n'est peut-être "pas beaucoup utilisé" par chaque programme dans le monde, mais peut-être que chaque programme est beaucoup utilisé. Au global, tu fais perdre au monde de la performance.
(C'est pour ça que ta bibliothèque de classes et ta chaîne d'outils de compilation doit toujours être au top de la perfection pour le code qui sera utilisé souvent "en général". Et les petits gars de .NET appliquent en général bien ce concept.)

./12 > En pratique, en mode débogage, VS a besoin de plein d'informations pour une raison x ou y, et le compilateur C# va générer de l'IL qui facilitera la vie au débogueur, avec la coopération du JIT, qui générera de l'assembleur qui facilitera la vie au débogueur (optimisations minimales). Dans ce cas là, je vois mal pourquoi, mais c'est difficile de dire. Si ton code généré en "release" est bon, alors c'est bon.

(Sinon, tu as avancé sur tes bugs étranges de code dynamique ? ^^)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

14

GoldenCrystal (./13) :
au niveau du monde entier, tu as consommé n*x cycles CPU en trop chaque minutes, et tu as dépensés je ne sais combien de kWh à cause de ce phénomène.
C'est pas quoi je sois pas d'accord avec toi, au contraire, mais si tu appliques ce raisonnement jusqu'au bout, tu n'utilises pas .NET ^^ (ni plein d'autres langages/technologies qui font bien pire de ce point de vue)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

15

epee
GoldenCrystal (./13) :
(Sinon, tu as avancé sur tes bugs étranges de code dynamique ? ^^)

Je n'y ai pas re-regardé pour le moment, j'essaie d'implémenter le double saut des chasseurs de démons sur Legion, ce qui nécéssite d'aller fouiller dans IDA grin

16

./14 > Ben heu, l'assembleur généré par le JIT .NET est tout à fait honorable la plupart du temps. Dans certains cas, le runtime a les cartes pour faire mieux mais à un prix plus élevé mais ne le fait pas (contrairement à Java), mais en dehors du temps de compilation, les environnement fortement typés à JIT fonctionnent plutôt pas mal. Sinon, on en vient à dire que comme aucun compilateur C/C++ ne génère de l'assembleur parfait, alors il ne faut pas faire de C/C++. cheeky

./15 > Crado tongue
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

17

(bon, on va pas relancer ce débat de toute façon, c'est pas le sujet pour ^^)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

18

./13 : #lag# OK, merci pour les explications mais ça reste théorique, je serais curieux de mesurer en pratique combien on perd avec un code qui utilise beaucoup d'async et de delegates vs un code écrit de façon à faciliter le travail du JIT au maximum. C'est une étude pas évidente à faire donc on aura probablement pas la réponse dans ce sujet, mais si un article en parle déjà ça sera un bon lien à poster ici smile (je googlerai à l'occasion et je posterai si je trouve quelque chose)
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

19

Pour info, y'a pas mal de discussions sur les optimisations possibles (et du coup celles déjà implémentées) côté JIT dans divers cas de génération de code sur github: https://github.com/dotnet/coreclr/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aoptimization%20
J'avais zieuté quelques sujets, et j'ai au moins appris un truc intéressant… Aujourd'hui le JIT sait optimiser les conditions sur les champs static readonly… Du coup si tu veux du code conditionnel au moment du JIT (par exemple sur les types génériques, en fonction de leur(s) paramètre de type), le workaround recommandé aujourd'hui semble être d'utiliser un champ static readonly qui précalcule le résultat de ta condition ^^ (En contrepartie le code qui est dans la branche "fausse" de ton if/else sera complètement ignoré smile)
À part ça, il manque encore pas mal de trucs, mais les développeurs en sont conscients, donc ça finira par venir ^^
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes