|
-
Mar 23rd, 2023, 07:23 AM
#23
Re: VB6 0xc0000005 on Windows 11 after calling *any* API
Wanted to get back to this thread for a while. Was busy with some real life stuff.
 Originally Posted by taishan
Niya, I didn't make myself clear, and I don't want to dis the choice of your programming language. I wasn't implying .NET had anything to do with P-Code. I didn't use VB5 because of P-Code. I still used QuickBasic, Pascal, or Delphi.
I was taking issue with the fact that your statement implies that .Net is slower than VB6 which is quite wrong. I get that you don't like .Net and that's fine but claims of .Net being slower because of it's framework or it's bytecode is just flat out wrong. That's all I was trying to point out.
 Originally Posted by The trick
Actually x64 gives the quite performace boost so .NET exectuables will give the better performance i guess. Moreover .NET execuatebles have JIT compiler which makes the native code so the performance degrade should be only for the first run i guess. I'm not a .NET expert and i can be wrong.
I've observed this to be the case in a few instances.
 Originally Posted by fafalone
I don't suppose you have numbers to back up this attitude... I'd bet that you have to go very far out of your way in .NET to match VB6, rather than the other way around. If you went out of your way in VB6, into the techniques on vbspeed and asm thunks, spanning and whatever else you want to do in .NET isn't coming within a gigaparsec of VB6.
This isn't even close to being true. Let's just at a classic favorite for benchmarking, summing vectors:-
Code:
Public Sub VectorSum(ByRef v1() As Long, ByRef v2() As Long, ByRef result() As Long)
Dim i As Long
For i = 0 To UBound(v1)
result(i) = v1(i) + v2(i)
Next i
End Sub
That is a very naïve implementation of a function that sums two equal size vectors and writes the result to a 3rd vector. When I compile this with all optimizations enabled and execute it to add two Long vectors with 300 elements it takes around 1300 nanoseconds to complete.
Now before I get to how .Net performs I just want to introduce the concept of a cold start. The .Net has runtime environment has a number of non-deterministic algorithms running in the background that tunes the way a .Net application runs. This includes the GC and JIT. This tends to negatively affect performance at the start-up of a .Net application. However, it quickly stabilizes into a stead state.
Here is a C# version of the same vector summing function:-
Code:
public static void VectorSum(int[] v1, int[] v2, int[] result)
{
for (int i = 0; i < v1.Length; i++)
result[i] = v1[i] + v2[i];
}
With a 32 bit debug build cold start this takes around 1500 nanoseconds which is in the vicinity of the fully optimized VB6 version. With a 32 bit release build cold start, it takes about 700 nanoseconds which is about twice as fast. A 64 bit release build cold start took about 400 nanoseconds which is in the vicinity of 4x faster than the slowest times measure so far.
Using BenchmarkDotNet, I was able to measure it's actual performance unaffected by the noise of a cold start. Compiled as 64 bit release build and executed when the environment is stable it took around 160 nanoseconds.
So to recap:-
| VB6 fully optimized release build |
1600 ns |
| .Net 32 and 64 bit cold start debug build |
1600 ns |
| .Net 32 bit cold start release build |
700 ns |
| .Net 64 bit cold start release build |
400 ns |
| .Net 64 bit "warm run" release build |
160 ns |
Just for fun I decided to throw in a C# Avx2 version of the vector sum function:-
Code:
public unsafe static void VectorSumAvx(int[] v1, int[] v2, int[] result)
{
if (!Avx2.IsSupported) throw new Exception("Avx2 is not supported on this device.");
Vector256<int> vec1;
Vector256<int> vec2;
//Make sure the lenth is evenly divisible by 8
int len = (v1.Length / 8) * 8;
int remainders = v1.Length % 8;
fixed (int* pv1 = v1, pv2 = v2, pvrec = result)
{
// Might as well be writing x86 assembly here.
// This code copies array values into the YMM registers
// 8 at a time, adds them and write the sums back
// to memory in the result array
for (int i = 0; i < len; i+=8)
{
// Load 8 integers from each array
// into YMM registers
vec1 = Avx2.LoadVector256(pv1 + i);
vec2 = Avx2.LoadVector256(pv2 + i);
// Add all 8 pairs of integers in YMM registers
// simluntaneously using the VPADDD x86 instruction from
// the AVX2 subset of SIMD instructions.
var r = Avx2.Add(vec1, vec2);
// Write the result of the additions
// back to memory.
Avx2.Store(pvrec + i, r);
}
}
// Handle remainders normally.
for (int i = len, x = 0; x < remainders; i++, x++)
{
result[i] = v1[i] + v2[i];
}
}
A 64 bit release build warm run of the above takes 37 nanoseconds, that a little more than 4x faster than the previous fastest speed and around 43x faster than a non-vectorized version executing in a fully optimized VB6 release build!
The .Net compiler I used for all these tests is from .Net 6 by the way, which might as well be a dinosaur. We are already on .Net 8 now. .Net 6 is outdated tech.
So what does this all mean? It means that .Net is fast, very very fast.
Now again, to be clear, this isn't to say that it's not possible to achieve a performance of 37 nanoseconds in VB6. I'm 100% certain you guys are more than talented enough to achieve it. My point is to dispel this persistent myth that .Net is a slow platform. The only real advantage VB6 developers have in terms of raw performance is that they don't have to content with cold starts. Outside of that very narrow scenario, .Net is blazing fast.
One more thing, I'm not a benchmarking expert, especially not with VB6 so I could have screwed up somewhere measuring in VB6. I'll post the full VB6 code in the next post, maybe you guys can tell me if I screwed something up that made this test unfair.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|