-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Fix opcodes from vb compiler when initialize an array and function local variant, jump invoke and delegate invoke. #519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
|
Hi @mikedn ,
|
And here's the code generated when overflow checks are disabled, the
As for code size - that's complicated. I'm not even sure if it has something to do with the code size, it may be related to the number of local variables. In any case, I looked at the code generated by the JIT compiler long enough to know that code quality suffers when the methods are large/complicated. And let's not forget that there are at least 3 different JIT compilers out there and each has different characteristics. |
@RevensofT I think "extra" |
Hi @AdamSpeight2008 ,
VB code
IL code (my test project's name is ILTest)
As you see, only thing those method are difference is Fat method has local variant (I need to do this on CIL because compiler will rid any unused local variant.) Result
As you see, Thin method alway faster then Fat method and only thing that difference between those 2 is one has local variant and other not.
|
You should probably open a separate issue for this specific point and clearly state that you expect the IL to be optimized. The compiler team can then decide what to do about this and other expression optimization issues - for example
|
|
The results for a release build are:
Clearly, your results are much closer to my debug results. Maybe you're running a release build but you're running in the debugger (F5). By default VS debugger disables JIT optimizations so what you get are really debug results.
|
About C# delegate, it has
|
Update for 4) test code. VB code
CIL code
Result
Update 5) test code.
Result
I'm sure I'm not doing bias about this test but result is very large difference between 2 method. @mikedn |
IL loop code:
The VB loop code already looks very much as you suggested - the JIT compiler replaced the Invoke call with the x86 equivalent of 2 The reason why the IL loop is slightly faster is that it lacks the 2 memory reads that corresponds to those 2 flds - the 3 locals that you use in the IL version end up being stored in registers. So, even if the VB compiler follows your suggestion the results will very likely be identical to what you have now. It's technically possible for the JIT compiler to produce IL loop like code from the VB loop. It just has to take advantage of the fact that delegates are immutable, that would allow it to hoist the ldflds outside the loop. |
Public Sub Add(A As Integer, B As Integer)
Dim x As Integer = A + B
x += x
End Sub |
By the way, talk about register memory I really curios what's data it stored ? Is it address of local variant or value of it ? Is field address and method address stored in register memory too ? |
The main factor that decides inlining is the native code size - the larger the code, the smaller the chance that the method will get inlined. The .NET's JIT compiler also pays attention to the number of local variables, if there are too many it gives up inlining. Assigning to a method argument always prevents inlining (in the current JIT compilers). Exception handling (try/catch) also prevents inlining. Crossing security boundaries also prevents inlining but it's less likely that you'll run into such cases.
Registers are basically small but very fast pieces of memory in the CPU. Anything that doesn't exceed the register size (32/64 bits usually) can be stored in a register - that includes integers, doubles, pointers/addresses, references. The thing is that there is a limited number (8-32) of registers available and the number varies from CPU to CPU. Deciding what variables should be stored in registers is an important compiler optimization and it can impact other optimization as well. That's one reason why managed compiler don't do many optimizations and leave most of the work to the JIT compiler.
If I understand correctly you want to be able optional parameters with delegates in VB. I think you should create a separate issue for this, I haven't seen this request before and since C# allows this it makes sense that VB should allow it too. |
I see, I'm test it(base on
I see, registers is on CPU cache(I guess it should be on L2 or L1). About delegate, yes, I mean optional parameters, when I wrote that I think about C# team can do something about their delegate that mean VB team could too( but it's fine now, I know delegate invoke method is just a sugar syntax). However, no one request optional delegate yet ? I'm stay away from delegate(include relaxed delegate conversion) much as possible because I think it drag performance of code down(at less, it prevent inlining), I think I should investigate about it , thank you for your suggestion. |
Indeed, in the x86 JIT compiler that limit is 8. There's also a limit of 10 for the number of method arguments. RyuJIT appears to have increased both limits to 32.
I doubt that there's a particular native code size limit, it's likely that the limit depends on other factors. At a minimum the limit should increase with the number of arguments. It may also depend on AggresiveInlining.
Not cache, the registers are in the CPU core itself. Cache access is actually slow compared to register access.
None that I know of here. |
Thanks, sadly it's not like RyuJIT will be apply to .Net soon.
All I can do is observe CIL code size, not much I can do to clarify inlining's conditions.
I try to use it before but it seem like I'm not understand its condition to work and a description in MSDN is really not help at all, "The method should be inlined if possible".
I see, thanks again. |
This issue reports five separate issues, and therefore is not really actionable. We'll split it up. |
none of the 5 issues seem to be a defect though. |
Hi guys,
I want to point out some flaw opcodes that vb compiler create and hope VB dev team have sometime to fix those and make VB better performance.
When I create an array like this "Dim Data(input.Length - 1) As Char", compiler will rewrite to "Dim Data(input.Length - 1 + 1) As Char"; it's unnecessary 4 bytes and you loss 4 of 64 bytes if you aim to create a tiny method.
VB function away has self local variant like "Function foo() As string" will have "Dim foo As String" even it's unused and it bad for performance when you aim to create tiny method header, even a single local variant will make it become a fat method header.
Jump invoke might be not fast as call or callvirt but it's safe for a stack overflow error and recursive method.
4) Delegate invokeInstead to use invoke method of delegate class, make it become sugar syntax.
Cost for invoke method is really high, less method invoke more performance.
Long method is hard to read and maintain but it's not suffer from method invoke cost, an inline method create by a non return method(aka Sub) could do this without any problem by use caller method's local variant as arguments of inline method.
Code will compile to this.
Local variant will not create any new local variant, anything else (maybe include a field of class for performance) will create a new local variant.
Ps. Sorry for no label, I can't add a label, don't see any option like in help document in topic apply labels to an issue.
The text was updated successfully, but these errors were encountered: