 |
|
 |
great idea!
just implemented it in our app
|
|
|
|
 |
|
 |
Quick, short and sweet explanation.
Thanks!
|
|
|
|
 |
|
 |
Hiya! What you are effectively presenting in your article is a code snippet with very little explanation of how to actually use it. And even then, it seems you haven't tested it enough to determine that, e.g., abstract methods cannot be jitted (somewhat obvious). You also don't take care of permissions, do not handle exceptions, and do not include cancellation of any sort. So if a developer on my project added this sort of code I'd be, well, not upset, but I would very much like an explanation of precisely why this type of method-wise prejitting was chosen as opposed to some other method. I'd also need proof that all potential errors are mitigated so that a customer doesn't get an ArgumentException when some late-bound assembly fails to pre-JIT.
Still, I don't want to appear more negative than I should - after all, this post gave me some food for thought, and for that I'm thankful.
|
|
|
|
 |
|
 |
The intention was not to provide piece of production-ready code (well tested and all-possible-situations-and-exceptions-ready code). I just wanted to show an idea, an example how to do it. That's it. And that's the reason article is posted in HOW-TO section. If anyone would pay me for that - I'd provide code snippet you would be surprised by!
I don't mind some criticism . Thanks for feedback. Nothing personal.
Vitaliy Liptchinsky
|
|
|
|
 |
|
 |
System.EntryPointNotFoundException
-----------------
Der Einstiegspunkt "TaskDialogIndirect" wurde nicht in der DLL "ComCtl32" gefunden.
-----------------
bei System.Runtime.CompilerServices.RuntimeHelpers._PrepareMethod(IntPtr method, RuntimeTypeHandle[] instantiation)
bei ZetaTest.Main.Code.AppHost.Host.b__4() in C:\Users\ukeim\Documents\Visual Studio 2008\Projects\Zeta Test\Zeta Test Main\Source\Main\Code\AppHost\Host.cs:Zeile 780.
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
EntryPointNotFoundException
{
Message="Der Einstiegspunkt \\"TaskDialogIndirect\\" wurde nicht in der DLL \\"ComCtl32\\" gefunden.",
TypeName="",
Data=ListDictionaryInternal
{
Count=0,
Keys=NodeKeyValueCollection
{
},
IsReadOnly=False,
IsFixedSize=False,
IsSynchronized=False,
SyncRoot=Object
{
},
Values=NodeKeyValueCollection
{
}
},
InnerException=null,
TargetSite=RuntimeMethodInfo: _PrepareMethod,
StackTrace=" bei System.Runtime.CompilerServices.RuntimeHelpers._PrepareMethod(IntPtr method, RuntimeTypeHandle[] instantiation)\\r\\n bei ZetaTest.Main.Code.AppHost.Host.b__4() in C:\\Users\\ukeim\\Documents\\Visual Studio 2008\\Projects\\Zeta Test\\Zeta Test Main\\Source\\Main\\Code\\AppHost\\Host.cs:Zeile 780.\\r\\n bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)\\r\\n bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)\\r\\n bei System.Threading.ThreadHelper.ThreadStart()",
HelpLink=null,
Source="mscorlib"
}
|
|
|
|
 |
|
 |
Hi Uwe,
I'm only 5 months in Austria and Ich spreche Deutsch nicht so gut
But from what I understand you are trying to pre-JIT method with external implementation (like marked with DLLImportAttribute). Am I correct?
Generally I would avoid pre-JITing of such methods.
Vitaliy Liptchinsky
|
|
|
|
 |
|
 |
Thanks, Vitaliy, I only tried it on a German Windows, so therefore the error messages in German only.
I do not know how this happend, I just called your code.
Maybe I must omit further methods?
|
|
|
|
 |
|
 |
What did the trick:
...
var attributes =
method.GetCustomAttributes(
typeof( DllImportAttribute ), false );
if ( attributes == null || attributes.Length <= 0 )
{
RuntimeHelpers.PrepareMethod( method.MethodHandle );
}
...
|
|
|
|
 |
|
|
 |
|
 |
Chris Richner wrote: http://www.codeproject.com/script/Forums/View.aspx?fid=783605&msg=2831349[^]
Sorry, Chris. Not sure I understand this...
Vitaliy Liptchinsky
|
|
|
|
 |
|
 |
No Problem, Vitaliy.. it's related to the System.EntryPointNotFoundException that was mentioned in the thread. I'm facing the same exception when I try to use Task Dialog API if no message loop is running.
|
|
|
|
 |
|
 |
I found this post to be very useful. I did find that when loading referenced assemblies it is useful to wrap the PrepareMethod in a try/catch block as the call may fail with an exception of some kind. Since I am using some 3rd party assemblies in my project, you never know how they may fail.
For example, I have a dependency on mscorlib where Win32Native/FindNLSString generates the following exception
System.EntryPointNotFoundException: Unable to find an entry point named 'FindNLSString' in DLL 'kernel32.dll'.
at System.Runtime.CompilerServices.RuntimeHelpers._PrepareMethod(IntPtr method, RuntimeTypeHandle[] instantiation)
at System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(RuntimeMethodHandle method)
Just a suggestion
Neil Lamka
neil@meetingworks.com
|
|
|
|
 |
|
 |
Nice article mate.
If you all havent caught up with PDC2008 then Anders gave a fantastic presentation on Future of C# and he showed that in C# 5.0 they are going to expose the compiler. ie. you can use Compiler as Service.
You can watch the video here.. I recommend it for every C# user.
WMV-HQ[^] | WMV[^] | Zune[^]
------------------------------------------------------------------
Life would have been much easier if I had the source-code!!
|
|
|
|
 |
|
|
 |
|
 |
Nice solution, but I think the best soultion is creat a small loader, when the user start the app, the loader first loaded and then display a animation to indicate the user the app doing something in background.
The God created the world.
The programer made the world easy.
|
|
|
|
 |
|
 |
First of all: this is one of the coolest things I ever saw in here
I took it as is, and place it into my 80+ assemblies client, and I must say it looks like it does response better. I did a very non scientific measurements using my logs, and saw about ~20% improvement overall.
Some notes about the snippet:
1) As others has mentioned here earlier, it is important to protect from abstracts and generics at the method level. I avoided interfaces and generic definition at type level to make it a bit more efficient.
2) I found out that this PrepareMethod method actually initiate the type itself. This gave me trouble in places where I had code in a static constructor, so I ignored types with static constructors all together.
3) Last, but not least, I used it to prepare all the assemblies referred to by my bootstrap, skipping the ones from the Global-Cache (a decision that might not fit everyone).
For reference, this is my version:
Thread jitter = new Thread(delegate()
{
foreach (System.Reflection.AssemblyName an in
System.Reflection.Assembly.GetEntryAssembly().GetReferencedAssemblies())
{
System.Reflection.Assembly asmb = System.Reflection.Assembly.Load(an);
if (!asmb.GlobalAssemblyCache)
{
foreach (Type type in asmb.GetTypes())
{
if (!type.IsInterface && !type.IsGenericTypeDefinition)
{
System.Reflection.ConstructorInfo ci = type.GetConstructor(
System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic, null, Type.EmptyTypes, null);
if (ci == null)
{
foreach (System.Reflection.MethodInfo method in type.GetMethods(
System.Reflection.BindingFlags.DeclaredOnly |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Static))
{
if (!method.IsAbstract && !method.IsGenericMethodDefinition &&
!method.ContainsGenericParameters)
System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
}
}
}
}
}
}
});
jitter.Priority = ThreadPriority.Lowest;
jitter.Start();
Ittay Ophir
levi_rami@yahoo.com
modified on Wednesday, December 3, 2008 9:14 AM
|
|
|
|
 |
|
 |
Hi Ittay.
Thanks for your feedback. I really appreciate it.
---->>> 2) I found out that this PrepareMethod method actually initiate the type itself. This gave me trouble in places where I had code in a static constructor, so I ignored types with static constructors all together.
PrepareMethod does not initiate class itself. Class is initiated when it is referenced first time. Here all classes are initiated in assembly.GetTypes() method.
Which problems did you have with static constructors?
Vitaliy Liptchinsky
|
|
|
|
 |
|
|
 |
|
 |
Yep, you are right. I think I missed it. Reflection does not instantiate the class, only reads metadata.
Thanks for sample!
Vitaliy Liptchinsky
|
|
|
|
 |
|
 |
As for the problem I had, it have to do with bad code design on my classes, so it is not relevant.
It is true that usually there should be no problem with static-constructors, even when called from this preparation routine.
Ittay Ophir
levi_rami@yahoo.com
|
|
|
|
 |
|
 |
I like your approach best. But you miss prejitting the entry assembly itself. I had to change your first Iteration to include the entry assembly like this:
List<assemblyname> assemblynames = new List<assemblyname>(Assembly.GetEntryAssembly().GetReferencedAssemblies());
assemblynames.Add(Assembly.GetEntryAssembly().GetName());
foreach (AssemblyName an in assemblynames) {
...
}
</assemblyname></assemblyname>
|
|
|
|
 |
|
 |
Getting errors on static methods and generic paramaterised methods.
Fixed with the following alteration.
Thread jitter = new Thread(() =>
{
foreach (var type in Assembly.GetEntryAssembly().GetTypes())
{
foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Instance ))
{
if (!method.IsAbstract && !method.IsGenericMethodDefinition && !method.ContainsGenericParameters )
{
System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
Console.WriteLine("{0} {1}", type.Name, method.Name);
}
}
}
});
jitter.Priority = ThreadPriority.Lowest;
jitter.Start();
|
|
|
|
 |
|
 |
better....
foreach (Type type in Assembly.Load(asm.FullName).GetTypes())
{
if (type.ContainsGenericParameters)
continue;
|
|
|
|
 |
|
 |
Hi Guys!
Thanks a lot for fixes!
Honestly, I haven't tested it with static and generic methods...
Vitaliy Liptchinsky
|
|
|
|
 |
|
 |
your hint is great man! Even if I'm thinking about compiling in native code to speed up!!
|
|
|
|
 |