Simple loop is slow compared to VB.NET - Forum - OpenEdge Development - Progress Community

Simple loop is slow compared to VB.NET

 Forum

Simple loop is slow compared to VB.NET

This question is answered

Just setting the stage here...I am not a 4GL expert but was trying to show our developers how to use background threads in VB.NET to use animated images on forms.  

So I created a Progress .NET form with a button and put this code in the click event so that the foreground thread would be busy..to show that animated images need their own thread or that the processing needed to be a separate worker thread from the form.

def variable i as integer init 0.
pictPleaseWait:Visible = true.
lblStart:Text = STRING(NOW).

process events.

do while i < 999999999 :

i = i + 1.

end.

pictPleaseWait:Visible = false.
lblEnd:Text = STRING(NOW).

RETURN.

Now here is the code on my vb.net form with code behind on click event.

Dim i As Integer = 0
lblStart.Text = Now.ToLongTimeString

pictPleaseWait.Visible = True

Application.DoEvents()

Do While i < 999999999

i = i + 1

Loop

pictPleaseWait.Visible = False
lblEnd.Text = Now.ToLongTimeString

 

The progress code takes minutes to run...the vb code takes seconds....

Any idea why?

 

Thanks,

Scott

Verified Answer
  • The Core Client team is committed to supporting and enhancing the ABL, which includes improving the performance of the language.

    The team has discussed the use of LLVM several times in the past and although we have not moved forward with a project which leverages this technology we are not opposed to integrating newer technologies into the product.  However, each project needs to be evaluated against the other projects which PM identifies as a priority for a release.  

    From time to time an example is posted to Community which highlights the performance other languages vs. the ABL.  We will continue to review these situations and if we determine there is a real benefit to the ABL we will investigate optimizing the Language.

    We have investigated and are continuing to analyze our OOABL infrastructure, looking for optimizations we can make.  When optimizations can be safely made, we implement these changes.

    The point of this thread is to identify that runtime performance is important and in that, there is agreement.  Working with PM, this development effort must be prioritized with the team’s other development tasks.

    Evan Bleicher

    Sr. Development Manager

    Progress Software

All Replies
  • > def variable i as integer init 0.

    Try to add NO-UNDO.

  • No difference..

  • The Progress code is compiled to a platform neutral format which is then interpreted by the AVM.  The VB code is compiled to an X86 executable.

    --
    Tom Bascom
    tom@wss.com

  • The NO-UNDO does improve my performance by about 40%.  Now since it takes 12 minutes to run the loop alone in my ABL, it may not be noticeable unless you're letting it run all the way through.  

    I would imagine that the .Net compiler is using more optimization and realizes that your Loop isn't actually doing anything so it cuts down on the computation.  I'd be curious what your timings look like if you actually did something(such as write to a log for each iteration) during your .Net loop.  

  • Try

    do i = 1 to 999999999:

    end.

    Maybe not as fast as vb, but much faster.

  • I will try that..but begs the question..what other 4GL functions are magnitudes slower...I mean, I wouldn't complain if 4GL was 10 seconds vs 3 seconds but this example is supercalifragilisticexpialidociously slower.

  • Frankly, I tend to agree!  It seems unreasonably slower.  Yes - the DO WHILE took about 15 minutes on my machine!  The DO i = 1 to 999999999 took 5.6 minutes.  That was without NO-UNDO.  That difference in itself seems odd.  And with NO-UNDO, it took 3.15 minutes.  That also seems odd since without a database transaction in effect, nothing would be undone anyway.  You could log a bug.

    And on a completely different note: What is the purpose of the PROCESS EVENTS/Application:DoEvents() in your example?

  • Actually, I tend to agree!   Too much of a difference.

    On my Windows machine:

      the DO WHILE took about 15 minutes!  

      DO i = 1 TO 999999999 took about 5.6 minutes

    That difference in itself seems odd.  That was without NO-UNDO.

    With NO-UNDO, the DO i = 1 TO 999999999 took 3.15 minutes.  That also seems odd since without a database transaction, nothing would have gotten undone anyway.

    You could log a bug.

  • I assume there is not JIT compiler in the AVM?

  • When you use a DO WHILE, I believe the condition is reevaluated after each iteration, which would explain why it's slower than just a DO loop. With the NO-UNDO statement, Progress skips the transaction back-out tracking so it's even faster.

  • So I added some code in vb.net loop to see if it is "short cutting" or if compiler is causing a premature exit of the loop.

    I defined a filewriter and streamwriter and output the following...

    Do While i < 999999999

               stream.Write("scott" + vbCrLf)

               i = i + 1

    Loop

    It when from 3 seconds to 70 seconds...still faster than 4GL even when doing disk IO.

    Odd..

  • Process-events is in the trigger to allow the main form to enable the .NET picture box with an animated gif.

  • Using C# instead of visual studio and using ilspy to see what this does:

    This is what the byte code looks like.  The compiler converted my while loop to a for loop and removed the increment on the integer.  So it becomes a do nothing loop.  I suspect if I ran this a few hundred times the JIT would throw out the loop completely.

    Original version:

    Using C# instead of visual studio and using ilspy to see what this does:

    // ConsoleApplication2.Program
    
    private static void Main(string[] args)
    
    {
    
    int i = 0;
    
    while (i < 999999999) {
    
     i = i + 1;
    
    }
    
    Console.WriteLine("done");

    bytecode version

    // ConsoleApplication2.Program
    
    private static void Main(string[] args)
    
    {
    
    for (int i = 0; i < 999999999; i++)
    
    {
    
    }
    
    Console.WriteLine("done");
    
    }
  • Double entry removed

  • I did a comparison between ABL and .Net a few months ago. I wrote a double loop with 2 vars, X and Y and let them loop from 1 to 1000 while calculating the Pythagorean theorem for both like this;

    DEFINE VARIABLE X AS INTEGER NO-UNDO.
    DEFINE VARIABLE Y AS INTEGER NO-UNDO.
    ETIME(YES).
    
    DO X = 1 TO 1000:
      DO Y = 1 TO 1000:
        SQRT(X * X + Y * Y).
      END.
    END.
    
    MESSAGE ETIME VIEW-AS ALERT-BOX INFO BUTTONS OK.

    This took around 1060 msec on my computer. The same solution in c# was about 100 times faster in ~ 10msec. The power of .Net runs circles around an ABL solutions in terms of performance. I guess this is the penalty for working in a language that is highly optimized to work with transactions and databases.

    While I was working on it, I also tested these variations:

    • Remove NO-UNDO -> 1462 msec
    • Use SQRT(EXP(X,2) + EXP(Y,2)) -> 2060 msec
    • Use DECIMAL instead of INTEGER -> 2473 msec
    • All of the above -> 2985 msec