[RESOLVED] Make this faster-VBForums
Results 1 to 10 of 10

Thread: [RESOLVED] Make this faster

  1. #1

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Resolved [RESOLVED] Make this faster

    My friend and I are comparing VB's speed to C++, and so far his is a lot faster (about 10 x's).

    Maybe some speed guru could help make this even faster using some APIs I probably don't know about or other techniques? It's basically math.

    Anyway, here's my code, followed by his C++ code.

    Code:
    Option Explicit
    
    Private Const MILLION As Long = 1000001
    
    Private Type Vector
        x As Long
        y As Long
        z As Long
    End Type
    
    Private Type LARGE_INTEGER
        LowPart As Long
        HighPart As Long
    End Type
    
    Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
    Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    
    Private udtStart As LARGE_INTEGER, udtEnd As LARGE_INTEGER
    Private curStart As Currency, curEnd As Currency
    Private udtFrequency As LARGE_INTEGER, curFrequency As Currency
    
    Private Sub Vector_Add(ByRef TheVector As Vector, ByVal Factor As Long)
        
        With TheVector
            .x = .x + Factor
            .y = .y + Factor
            .z = .z + Factor
        End With
        
    End Sub
    
    Private Sub Vector_Multiply(ByRef TheVector As Vector, ByVal Factor As Long)
        
        With TheVector
            .x = .x * Factor
            .y = .y * Factor
            .z = .z * Factor
        End With
        
    End Sub
    
    Private Sub Vector_Divide(ByRef TheVector As Vector, ByVal Factor As Long)
        
        With TheVector
            .x = .x / Factor
            .y = .y / Factor
            .z = .z / Factor
        End With
        
    End Sub
    
    Private Function LargeIntToCurrency(ByRef LargeInteger As LARGE_INTEGER) As Currency
    
        CopyMemory LargeIntToCurrency, LargeInteger, LenB(LargeInteger)
        LargeIntToCurrency = LargeIntToCurrency * 10000
        
    End Function
    
    Private Sub Form_Load()
        
        If QueryPerformanceFrequency(udtFrequency) = 0 Then
            MsgBox "QPC not available on your piece of **** computer!", vbExclamation
            Unload Me
        End If
        
        curFrequency = LargeIntToCurrency(udtFrequency)
        
        Dim v1 As Vector, v2 As Vector, v3 As Vector
            
        With v1
            .x = 1
            .y = 2
            .z = 3
        End With
        
        With v2
            .x = 100
            .y = 200
            .z = 300
        End With
        
        With v3
            .x = 40
            .y = 50
            .z = 60
        End With
        
        Dim tmp1 As Vector, tmp2 As Vector
        Dim tmp3 As Vector, tmp As Vector
        
        tmp = v1
        'tmp += 1
        Vector_Add tmp, 1
        
        If tmp.x = 2 And tmp.y = 3 And tmp.z = 4 Then
            MsgBox "Test1: Ok!", vbInformation
        End If
        
        tmp = v2
        'tmp *= 2
        Vector_Multiply tmp, 2
        
        If tmp.x = 200 And tmp.y = 400 And tmp.z = 600 Then
            MsgBox "Test2: Ok!", vbInformation
        End If
        
        tmp = v3
        Vector_Divide tmp, 10
        
        If tmp.x = 4 And tmp.y = 5 And tmp.z = 6 Then
            MsgBox "Test3: Ok!", vbInformation
        End If
        
        '* Timed code begins here *
        'TIME_BEGIN:
        QueryPerformanceCounter udtStart
        
        Dim i As Long
        
        For i = 1 To MILLION
            
            'Vector 1
            'CopyMemory tmp, v1, 12
            tmp = v1
            
            'Add, multiply, divide
            With tmp
                .x = .x + i
                .y = .y + i
                .z = .z + i
                            
                .x = .x * i
                .y = .y * i
                .z = .z * i
                
                .x = .x / i
                .y = .y / i
                .z = .z / i
            End With
            
            'Vector 2
            'CopyMemory tmp, v2, 12
            tmp = v2
            
            With tmp
                .x = .x + i
                .y = .y + i
                .z = .z + i
                
                .x = .x * i
                .y = .y * i
                .z = .z * i
                
                .x = .x / i
                .y = .y / i
                .z = .z / i
            End With
            
            'Vector 3
            'CopyMemory tmp, v3, 12
            tmp = v3
            
            With tmp
                .x = .x + i
                .y = .y + i
                .z = .z + i
                
                .x = .x * i
                .y = .y * i
                .z = .z * i
                
                .x = .x / i
                .y = .y / i
                .z = .z / i
            End With
            
        Next i
        
        'TIME_END:
        QueryPerformanceCounter udtEnd
            
        curStart = LargeIntToCurrency(udtStart)
        curEnd = LargeIntToCurrency(udtEnd)
        
        '((end - start) / freq) * 1000)
        MsgBox ((curEnd - curStart) / curFrequency) * 1000, vbInformation
        
    End Sub



    C++ code:
    Code:
    #include <stdio.h>
    #include <windows.h>
    
    #pragma comment(lib, "kernel32")
    
    
    #define TIME_BEGIN double freq, start, end;                           \
    				   QueryPerformanceFrequency((LARGE_INTEGER *)&freq); \
                       QueryPerformanceCounter((LARGE_INTEGER *)&start);
    
    #define TIME_END    QueryPerformanceCounter((LARGE_INTEGER *)&end);   \
    					printf("Timer: &#37;f ms\n", ((end - start) / freq) * 1000);  
    
    struct vector
    {
    	double x, y, z;
    
    	void operator += (long f)
    	{
    		x += f; 
    		y += f;
    		z += f;
    	}
    	void operator *= (long f)
    	{
    		x *= f; 
    		y *= f;
    		z *= f;
    	}
    	void operator /= (long d)
    	{
    		x /= d; 
    		y /= d;
    		z /= d;
    	}
    };
    
    #define MILLION 1000000
    
    vector v1 = { 1.0,   2.0,   3.0   };
    vector v2 = { 100.0, 200.0, 300.0 };
    vector v3 = { 40.0,  50.0,  60.0  };
    vector tmp1;
    vector tmp2;
    vector tmp3;
    vector tmp;
    
    int main()
    {
    	tmp = v1;
    	tmp += 1;
    	if (tmp.x == 2.0 && tmp.y == 3.0 && tmp.z == 4.0)
    		printf("test1: Ok!\n");
    
    	tmp = v2;
    	tmp *= 2;
    	if (tmp.x == 200.0 && tmp.y == 400.0 && tmp.z == 600.0)
    		printf("test2: Ok!\n");
    
    	tmp = v3;
    	tmp /= 10;
    	if (tmp.x == 4.0 && tmp.y == 5.0 && tmp.z == 6.0)
    		printf("test3: Ok!\n");
    
    	TIME_BEGIN;
    	for (long i = 0; i < MILLION; ++i)
    	{
    			tmp1 = v1;
    			tmp1 += i;
    			tmp1 *= i;
    			tmp1 /= i;
    
    			tmp2 = v2;
    			tmp2 += i;
    			tmp2 *= i;
    			tmp2 /= i;
    
    			tmp3 = v3;
    			tmp3 += i;
    			tmp3 *= i;
    			tmp3 /= i;
    	}
    	TIME_END;
    	while (true);
    	return 0;
    }
    Edit: His code only takes about 5ms compared to mine, which takes about 500ms.
    Last edited by DigiRev; Aug 3rd, 2009 at 07:37 PM.

  2. #2
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    31,104

    Re: Make this faster

    Doesn't surprise me. Number crunching is what C/C++ does best. One of the reasons is that C/C++ will compile to native code, while VB, especially VB6 runs through an interpreter engine as it is running.

    You can try changing the compile otions to compile to NAtive code, see if the EXE runs any faster that way.

    There's a reason a lot of games and graphics intense applications are written in C/C++ and not VB.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  3. #3

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Make this faster


  4. #4

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Make this faster

    Not everything goes through the VB runtime, a lot gets compiled to true machine code.

    I had more faith in VB than I should have, I guess. With well-written code it seems to perform really well. Maybe just not at math.

    Anyway, we changed it to use Long instead of floating point, so if anyone has any ideas to make it faster, please post.

    I updated original post with new code.

  5. #5
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    31,104

    Re: Make this faster

    Sorry.. .that's not to say there isn't something that could be done... I've just never needed that level of speed like that, so I wouldn't know if there is something that could be done.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  6. #6
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: Make this faster

    Doing this kind of speed comparison is on almost the pointless side. One thing that should be accounted for is that C++ compilers generally optimize a whole lot. This means they may remove code and actually not do what has been written. This in turn means that people who don't know this start thinking C++ would somehow be more awesome than it really is (at times). VB's compiler does optimization too, but being based on a very old C compiler it doesn't have that many tricks in it's sleeve. In this case I think the C++ compiler may very well just execute the very last iteration of the loop, because the variables are never used for anything else so an intelligent compiler could very well do that.

    Speedwise, I think one of the issues is that you're using a Type. Also, the trust you have an API goes into vain: making a single API call costs a lot more processing power than you'd think, because VB does things such as tracking API errors automatically in the background, which means calling CopyMemory in VB6 takes far more time than it does in C++. The actual memory copy happens just as quickly, it is just all the other things that make things go slower than one would expect.


    A better comparison could be done with something that actually does something worthwhile and prevents C++ compiler to do code removing optimizations. Like, parse some kind of file data. However, an optimized C++ will still be likely to be faster, because VB6 doesn't provide stuff such as bitshifting, so you're forced to use slower methods to get the same results.


    Edit!
    You can just remove LARGE_INTEGER and replace it with Currency. No need to make a conversion function.
    Last edited by Merri; Aug 3rd, 2009 at 09:19 PM.

  7. #7

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Make this faster

    Quote Originally Posted by Merri View Post
    Doing this kind of speed comparison is on almost the pointless side. One thing that should be accounted for is that C++ compilers generally optimize a whole lot. This means they may remove code and actually not do what has been written. This in turn means that people who don't know this start thinking C++ would somehow be more awesome than it really is (at times). VB's compiler does optimization too, but being based on a very old C compiler it doesn't have that many tricks in it's sleeve. In this case I think the C++ compiler may very well just execute the very last iteration of the loop, because the variables are never used for anything else so an intelligent compiler could very well do that.

    Speedwise, I think one of the issues is that you're using a Type. Also, the trust you have an API goes into vain: making a single API call costs a lot more processing power than you'd think, because VB does things such as tracking API errors automatically in the background, which means calling CopyMemory in VB6 takes far more time than it does in C++. The actual memory copy happens just as quickly, it is just all the other things that make things go slower than one would expect.


    A better comparison could be done with something that actually does something worthwhile and prevents C++ compiler to do code removing optimizations. Like, parse some kind of file data. However, an optimized C++ will still be likely to be faster, because VB6 doesn't provide stuff such as bitshifting, so you're forced to use slower methods to get the same results.


    Edit!
    You can just remove LARGE_INTEGER and replace it with Currency. No need to make a conversion function.
    Those were my thoughts exactly. I even told him we should do something like file parsing and execution times would be much closer to each other.

    At first, he noticed that the compiler actually removed most of the code, but then he changed it so that it didn't (as far as I know anyway).

    I also ended up removing the CopyMemory call later on.

  8. #8
    Addicted Member reacen's Avatar
    Join Date
    Jul 2009
    Location
    c:\windows\system32\gdi32.dll
    Posts
    243

    Re: [RESOLVED] Make this faster

    You can use DLL/OCX ... Make the stuff that need Speek on C++ DLL, ans use it with vb ...
    DoEvents

  9. #9
    Addicted Member reacen's Avatar
    Join Date
    Jul 2009
    Location
    c:\windows\system32\gdi32.dll
    Posts
    243

    Re: [RESOLVED] Make this faster

    Make the stuff that need Speed (not speek sorry) xD
    DoEvents

  10. #10
    Member
    Join Date
    Oct 2006
    Posts
    46

    Re: [RESOLVED] Make this faster

    //edit: I'm sorry for digging this out, was searching for something and stumbled over it. Didn't check the date

    You could do an Integer division instead of a floating point one and, if allowed, "inline" the type copy:

    Code:
            With tmp
                .x = v1.x * i
                .y = v1.y * i
                .z = v1.z * i
                
                .x = .x \ i
                .y = .y \ i
                .z = .z \ i
                
                .x = .x + i
                .y = .y + i
                .z = .z + i
            End With
    .
    .
    .
    This runs a lot faster, it takes about 150 ms on my old laptop instead of 700 ms. But it's still slow, compared to the C code, which takes 25 ms with speed optimizations (350 ms without).
    Maybe this is because of missing operators like +=, -=, and so on.

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
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.