• (cs) in reply to Mike R

    Mike R:

    There has to be a logical flaw there, you put fast and java in the same sentence. C/C++ done right requires little "micromanagement."

    <FONT face="Courier New" size=2>in terms of performance, certain java apps run sluggish, but there are ways to correct that.  the "speed" comes from being able to design, use, and test objects effectively.  of course, i agree, you do that in C/C++ as well, except it's more tedious.  you have to program into your language, which takes a certain time investment upfront.  perhaps a time investment i should be doing right now.  i'll be back to do my afternoon rounds.</FONT>

  • (cs) in reply to Mike R
    Mike R:

    There has to be a logical flaw there, you put fast and java in the same sentence.


    That's statement is so last millenium.

    With modern JITs, well-written Java is no slower than well-written C. Unfortunately, Java has attracted a lot of bad programmers, possibly because it's easier to write non-trivial programs in.

    When a C/C++ program is slow and a memory hog (OpenOffice, anyone?), it's blamed on the programmer. When a Java program does the same, it's blamed on the language.
  • Calvin M Spealman (unregistered)

    I know most of you disagree, but several of you have hinted to the fact that this is actually not bad code. Checking a conditional every iteration is more intensive than the handling of a single exception. Some langauges even use this internally for iteration mechanisms.

  • Asd (unregistered) in reply to nick-less

    Bollocks:

    A few separate runs of your code:

    1st took 47
    2nd took 47

    1st took 47
    2nd took 63

    1st took 46
    2nd took 63

    1st took 62
    2nd took 63

    1st took 63
    2nd took 46


    Your code inside 1000x for loop:

    Total for first: 55461
    Total for second: 56867

    And of course that is not really a short loop. A short loop:
    Array size: 1000
    Iterations of test: 100000

    Total for first: 1749

    Total for second: 704

    Wow really impressive

  • Asd (unregistered) in reply to Asd
    Anonymous:
    Bollocks:

    A few separate runs of your code:

    1st took 47
    2nd took 47
    ...

    Targeted at nick-less


  • (cs) in reply to Calvin M Spealman
    Anonymous:
    I know most of you disagree, but several of you have hinted to the fact that this is actually not bad code. Checking a conditional every iteration is more intensive than the handling of a single exception. Some langauges even use this internally for iteration mechanisms.


    Yes, it actually IS very, very bad code. As has been pointed out, it's not even faster, but even if it were, it would be still bad code because it abuses the concept of exceptions for flow control. If a language uses something like that internally (which I doubt), that would be a different thing because it would not fuck up the code like this.
  • (cs) in reply to DannyB
    user="Anonymous"Sigh.
    You actually are missing something completely obvious.
    If he's trying to catch index out of bounds, it must throw it somewhere.
    The likely case is that it's doing an array check inside the function call to throw it.
    So he's got the overhead of both the try/catch, *and* the array check

    Actually, the function displayProductInfo gets passed a reference to an object, no a reference to a position in an array. The exception gets thrown when Java tries to retrieve the reference to the object that should stored in prodnums[idx]</cb>, but it finds out that idx >= prodnums.length(), so the funcion will never get called.

    This will be the function definition, notice it gets passed a reference to an object of class StupidProduct, not an array, neither an array index, nor a pointer to an array position, nor a pointer to an array position holding the reference to the actual object, nor any of the mad constructs you can assemble in C using "&" and "*" when passing parameters:

    void displayProductInfo( final StupidProduct s )
    {
      //some stupid code to handle stupid products.
      ......
      ......
      ......
      //notice the _final_ keyword, because you don't usually need
      //  to modify the object in order to display it, so we force
      //  the compiler to enforce non-modification of the parameter.
      //  If we accidentally write here code that changes the object, the
      //  compiler will refuse to compile so we will know that something
      //  weird is going on.
    }
    

    And this is the context for the loop:

    StupidProduct[] prodnums = new StupidProduct[many];
    populateStupidProduct(prodnums);
    try
    {
      int idx = 0;
      while (true)
      {
        displayProductInfo(prodnums[idx]);
        idx++;
      }
    }
    catch (IndexOutOfBoundException ex)
    {
      // nil
    }
    

    yes, "many" is global :)

  • (cs) in reply to brazzy
    brazzy:

    That's statement is so last millenium.

    With modern JITs, well-written Java is no slower than well-written C. Unfortunately, Java has attracted a lot of bad programmers, possibly because it's easier to write non-trivial programs in.

    When a C/C++ program is slow and a memory hog (OpenOffice, anyone?), it's blamed on the programmer. When a Java program does the same, it's blamed on the language.


    I'm sorry, I have yet to see a well-performing Java application, everything I see on Java Applications points to dismal performance. I'd truely love to see some sort of real-world benchmark between the two (I know it isn't exactly possible...but, would eliminate silliness like counting from 1-100 or some such)

    The other drawback is Java seems to lack the ability to "fit in" with its environment. i.e. gui controls and the like look foreign on Windows systems (but, I'm sure they look at home in Unix systems). Anyway, thats for another language war thread. The one thing Java is good for is "platform independence". Of course, I know I'll catch some heat for that one, but a language that compiles to bytecode and doesn't rely on system calls, and processor instructions has a much better chance at working on multiple platforms. I suppose the argument could be made that C could do the same thing if there was such a thing as a CVM.

    The C/C++ vs Java argument on blaming the programmer is simple: With C/C++ theres just simply no other excuse. With a language based on a VM, its easy to blame the VM.
  • (cs) in reply to Calvin M Spealman
    Anonymous:
    I know most of you disagree, but several of you have hinted to the fact that this is actually not bad code. Checking a conditional every iteration is more intensive than the handling of a single exception. Some langauges even use this internally for iteration mechanisms.


    While this particular case looks like a WTF, the pattern itself is sound.


      (from Python in a Nutshell)
    • The checks may diminish the readability and clarity of the common, mainstream cases, where everything is okay.
    • The work needed for checking may duplicate a substantial part of the work done in the operation itself.
    • The programmer might easily err by omitting some needed check.
    • The situation might change between the moment the checks are performed and the moment the operation is attempted.

    While it is true that exceptions often take 10 times as long as doing the checks, in most cases the code itself isn't performance critical anyway, so it doesn't matter in the least.   If catching an exception creates more readable code than checking bounds, than use exceptions and live with more readable code.  If catching exceptions doesn't make the code more readable, than check your bounds.


    I'd use a for loop if there was some way to get the number of elements.  However if displayProductInfo may alter the number of elements in prodnums, than this is the right solution to the problem.  (Note, a function called displayProductInfo shouldn't alter it, but a class method splitProductInfo might turn an assembly into component nuts and bolts)


    Note that I do most of my programing in python, where exceptions are not considered a bad thing.   Common C++ and Java style is to use exceptions only for unexpected bad situations, and  use return codes for bad situations that are expected to happen normally.    When in Rome, do as the Romans, so if you are a C++/Java programmer you can be excused for not using this pattern, even when it would make your code more readable, while in python you should (but remember the for x in foo example that someone else posted which is better in this particular case!).


    Python gives a stack trace when an exception is not caught, while C++ will not.   (At least not in the implementations I've used)   In python it is easy to figure out where to catch an unhanded exception, while I've spent days scratching my head trying to figure out where my C++ code threw that particular exception, and guessing at the stack after that to decide where to handle it.  This isn't the fault of exceptions, though it is another argument to not use them in C++.

  • (cs) in reply to Anonymous Coward
    Anonymous Coward:
    I:

    I bet you ran it in the debugger.  Compile as release code and try again, there's a huge speed difference in exception handling.

    I copied the code and tried it for myself.

    10 results of Ytram's code, run as a release build outside the debugger, show that exceptions are slower (as expected ;)), but not as badly as [s]he found:

    Bad Loop: 31 milliseconds
    Good Loop: 31 milliseconds
    Bad Loop: 15 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 15 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 31 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 15 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 31 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 31 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 31 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 31 milliseconds
    Good Loop: 15 milliseconds
    Bad Loop: 31 milliseconds
    Good Loop: 15 milliseconds

    This kind of expection handling remains crappy coding, of course.



    Good call.  I'm perpetually in debug mode.
  • (cs) in reply to emptyset
    emptyset:
    <font face="Courier New" size="2">isn't the entire heart of programming abstraction?  i think high-level languages are pretty cool since they eliminate the tedium assocated with many trivial programming tasks.  unfortunately, i haven't yet had the benefit of encountering such a language in this here "real-world" situation.</font>

    Absolutely right.  C++ itself is just another abstraction over assembly and assembly is just another abstraction over machine code.  C++ (the poster) is a hypocrite, plain and simple.

    The real debate is not about abstraction.  It is about what abstractions should be used, and how far we should go with them.
  • (cs) in reply to hank miller
    hank miller:
    Anonymous:
    I know most of you disagree, but several of you have hinted to the fact that this is actually not bad code. Checking a conditional every iteration is more intensive than the handling of a single exception. Some langauges even use this internally for iteration mechanisms.


    While this particular case looks like a WTF, the pattern itself is sound.

      (from Python in a Nutshell)
    • The checks may diminish the readability and clarity of the common, mainstream cases, where everything is okay.
    • The work needed for checking may duplicate a substantial part of the work done in the operation itself.
    • The programmer might easily err by omitting some needed check.
    • The situation might change between the moment the checks are performed and the moment the operation is attempted.


    While it is true that exceptions often take 10 times as long as doing the checks, in most cases the code itself isn't performance critical anyway, so it doesn't matter in the least.   If catching an exception creates more readable code than checking bounds, than use exceptions and live with more readable code.  If catching exceptions doesn't make the code more readable, than check your bounds.

    for (int i = 0; i < array.length; i++) is such a common idiom in Java that it's one of the most readable things out there.  In Java 1.5 you can do this:

    for (String s : array){
       doSomething(s);
    }

    In addition doing it the way it was done in this WTF screws with the compilers' ability to optimize the loop.

    hank miller:
    I'd use a for loop if there was some way to get the number of elements.

    Are you suggesting there isn't?

    hank miller:
    However if displayProductInfo may alter the number of elements in prodnums, than this is the right solution to the problem.

    As already pointed out, that is impossible and it's also irrelevant because arrays always have a length variable.

    hank miller:
    Note that I do most of my programing in python, where exceptions are not considered a bad thing.   Common C++ and Java style is to use exceptions only for unexpected bad situations, and  use return codes for bad situations that are expected to happen normally.    When in Rome, do as the Romans, so if you are a C++/Java programmer you can be excused for not using this pattern, even when it would make your code more readable, while in python you should (but remember the for x in foo example that someone else posted which is better in this particular case!).

    Python gives a stack trace when an exception is not caught, while C++ will not.   (At least not in the implementations I've used)   In python it is easy to figure out where to catch an unhanded exception, while I've spent days scratching my head trying to figure out where my C++ code threw that particular exception, and guessing at the stack after that to decide where to handle it.  This isn't the fault of exceptions, though it is another argument to not use them in C++.

    The cost of exceptions is built into all Python calls.  In Java, it's only costly if they are thrown.  So exceptions aren't free in Python anymore than heath care is free if you pay for insurance.

  • (cs) in reply to Chris F
    Chris F:
    The real debate is not about abstraction.  It is about what abstractions should be used, and how far we should go with them.

    Sorry, I meant to say: The real debate is not about whether abstraction should be used.
  • nick-less (unregistered) in reply to Asd
    Anonymous:
    Anonymous:
    Bollocks:

    A few separate runs of your code:

    1st took 47
    2nd took 47
    ...

    Targeted at nick-less




    hey,  target the guy who wrote this http://www.javaworld.com/javaworld/jw-04-1997/jw-04-optimize-p4.html ;-)
  • (cs) in reply to mizhi
    mizhi:
    Why is it so many developers insist on reinventing the wheel in the shape of a square or triangle?


    1) To paraphrase Plankton "...look at it, square the shape of evil."

    2) Many Christians believe in the Trinity - like a Triangle - so this must be the shape of things holy.

    3) Therefore the circle is the center of these shapes with the square on the left (since the left is evil) and the Triangle on the right (since the right is good). So good programmers must move all Circles to Triangles or they will always be known as Squares.

  • (cs) in reply to Mike R
    Mike R:

    I'm sorry, I have yet to see a well-performing Java application, everything I see on Java Applications points to dismal performance. I'd truely love to see some sort of real-world benchmark between the two (I know it isn't exactly possible...but, would eliminate silliness like counting from 1-100 or some such)

    What "well-performing" means depends on the task. If a program receives 10 requests per second and a Java program is able to handle that, it doesn't matter that the Java program could handle at most 500 requests per second while a C++ programm would be able to handle 1200 request per second. As far as GUI programs are concerned, I think that Swing is mostly the one to blame.


    The other drawback is Java seems to lack the ability to "fit in" with its environment. i.e. gui controls and the like look foreign on Windows systems (but, I'm sure they look at home in Unix systems).


    Using the "Windows" look&feel, they look reasonably familiar on Windows; but many Swing apps use the default "Metal" look&feel that looks equally foreign on all plattforms, including Linux/Unix/Mac.


    Anyway, thats for another language war thread. The one thing Java is good for is "platform independence". Of course, I know I'll catch some heat for that one, but a language that compiles to bytecode and doesn't rely on system calls, and processor instructions has a much better chance at working on multiple platforms. I suppose the argument could be made that C could do the same thing if there was such a thing as a CVM.


    The fact is: the JVM does exist while a CVM does not. If you require platform independence, the theoretical possibility of a CVM doesn't help you. Another problem with platform independend C (or C++) is that the definition of these languages leaves ambiguity so a C program can rely on behaviour of one specific plattform (like byte ordering, alignment etc.); this currently makes porting C sources difficult, even if you have the same libs (like posix) on the target platform.


    The C/C++ vs Java argument on blaming the programmer is simple: With C/C++ theres just simply no other excuse. With a language based on a VM, its easy to blame the VM.



    Well, a C++ programmer could always put the blame on the compiler, the libs or the system calls.

  • (cs) in reply to nick-less
    Anonymous:

    hey,  target the guy who wrote this http://www.javaworld.com/javaworld/jw-04-1997/jw-04-optimize-p4.html ;-)


    Note the date in the URL. And even there, it says:
    • <font face="verdana, arial, helvetica" size="3">In fact, consider using an exception to terminate a loop as a last-ditch effort</font>
    • <font face="verdana, arial, helvetica" size="3">If you're throwing exceptions regularly as part of the normal operation of your code, you may want to rethink your design.</font>
    • "<font face="verdana, arial, helvetica" size="3">Don't optimize unless you know it's necessary</font>"
  • Asd (unregistered) in reply to nick-less
    Anonymous:

    Well it might have been correct 8 YEARS AGO!

    Enric Naval:

    //notice the _final_ keyword, because you don't usually need
      //  to modify the object in order to display it, so we force
      //  the compiler to enforce non-modification of the parameter.
      //  If we accidentally write here code that changes the object, the
      //  compiler will refuse to compile so we will know that something
      //  weird is going on.

    This is not quite correct.
    We can't do:
    s = new StupidProduct();
    But we can do:
    s.setImportantMember(73);

    I wish it behaved like C++ const.

    Tony Morris:

    I work for a large software corporation. We distribute our own Java VM and J2EE application server...

    Ahaha. Now I have testimony to advise people against IBM. Now if only everyone else wasn't just as crap :P
  • Samuel (unregistered) in reply to Asd

    Huh, one must be pretty desperate to look this kinds of optimizations. I bet there is much better places to optimize than loop invariants.

  • (cs) in reply to Mike R

    Mike R:
    brazzy:

    That's statement is so last millenium.

    With modern JITs, well-written Java is no slower than well-written C. Unfortunately, Java has attracted a lot of bad programmers, possibly because it's easier to write non-trivial programs in.

    When a C/C++ program is slow and a memory hog (OpenOffice, anyone?), it's blamed on the programmer. When a Java program does the same, it's blamed on the language.


    I'm sorry, I have yet to see a well-performing Java application, everything I see on Java Applications points to dismal performance. I'd truely love to see some sort of real-world benchmark between the two (I know it isn't exactly possible...but, would eliminate silliness like counting from 1-100 or some such)

    The other drawback is Java seems to lack the ability to "fit in" with its environment. i.e. gui controls and the like look foreign on Windows systems (but, I'm sure they look at home in Unix systems). Anyway, thats for another language war thread. The one thing Java is good for is "platform independence". Of course, I know I'll catch some heat for that one, but a language that compiles to bytecode and doesn't rely on system calls, and processor instructions has a much better chance at working on multiple platforms. I suppose the argument could be made that C could do the same thing if there was such a thing as a CVM.

    The fact of the matter is that you may be using a Java app and never know it.  A lot of web servers use Java.  I personally know how to write and provide a Java application without you having to install Java or see any reference to it.

    The GUI not fitting in thing is not Java it's a library.  Java has no built-in gui funtionality, it's just a language.  The problem is that Swing reinvented every widget in Java code.  It was a silly way to implement cross-platform functionality IMO.

    IBM provides a GUI API called SWT (Standard Widget Toolkit) that uses native OS widgets as much as it can.  A SWT app looks and behaves just like any other application on the OS.

  • Name here: (unregistered) in reply to brazzy

    It's blamed on the Java language because Java has the garbage collector, and it's supposed to free the objects.

    How do you free an object in Java?

  • (cs) in reply to Name here:
    Anonymous:

    It's blamed on the Java language because Java has the garbage collector, and it's supposed to free the objects.

    How do you free an object in Java?

    You don't.  The garbage collector does.

  • (cs) in reply to brazzy
    brazzy:
    it would be still bad code because it abuses the concept of exceptions for flow control.


    I've seen programs that use exceptions to do a jump... just like you would do with GOTO.
    Looks like that (the language is PL/SQL):

    function doSomething return number is finished exception; retcode number := 1; begin if notActive then raise finished; end if;

    retcode := doSomething; /* several pages of code for the actual work to do */

    raise finished; return retcode; exception when finished then trace('Finished with retcode '||retcode); return retcode; when others then trace('Crashed with '||sqlerrm); return -1; end;

  • (cs) in reply to Chris F

    Chris F:
    Chris F:
    The real debate is not about abstraction.  It is about what abstractions should be used, and how far we should go with them.

    Sorry, I meant to say: The real debate is not about whether abstraction should be used.

    <FONT face="Courier New" size=2>well, at some point, unfounded java bashing occured.  there are some pretty valid criticisms of the java infrastructure, but overall, the concept of having a virtual machine is pretty cool.  in C/C++, you really don't have the liberty to *completely* forget about the underlying hardware, though good practices can mitigate that.</FONT>

    <FONT face="Courier New" size=2>it's a damn shame smalltalk didn't take off: i have much heart for the language.  it's been taken over by the squeakers.</FONT>

    <FONT face="Courier New" size=2>*shudders*</FONT>

  • (cs) in reply to Mike R

    Your post is based largely on conjecture and/or ignorance

    Mike R:
    I have yet to see a well-performing Java application

    So they don't exist?
    Mike R:
    The other drawback is Java seems to lack the ability to "fit in" with its environment. i.e. gui controls and the like look foreign on Windows systems

    Although the Windows PLAF in Swing is a bit awkward, download Eclipse (SWT) and tell me what doesn't "fit in."
    Mike R:
    I suppose the argument could be made that C could do the same thing if there was such a thing as a CVM

    Pointless, since it doesn't exist.  Besides, if you didn't drink the M$ kool-aid, you would be developing (nearly) platform independent C.

    Mike R:
    With a language based on a VM, its easy to blame the VM.

    Of course it's easy to cast blame on the VM...when you're ignorant of it.

    http://img.photobucket.com/albums/v84/wannabeshoes/KoolAidManII.jpg
  • (cs) in reply to Asd
    user="Enric Naval"
    //notice the _final_ keyword, because you don't usually need
      //  to modify the object in order to display it, so we force
      //  the compiler to enforce non-modification of the parameter.
      //  If we accidentally write here code that changes the object, the
      //  compiler will refuse to compile so we will know that something
      //  weird is going on.

    This is not quite correct.
    We can't do:
    s = new StupidProduct();
    But we can do:
    s.setImportantMember(73);

    I wish it behaved like C++ const.

    Ouch! You are right. I forgot that gotcha.

  • (cs) in reply to kipthegreat
    user="kipthegreat"
    user="Anonymous"
    Reminds me of a company I worked at once, where they were writing a custom app server.  Step 1: rewrite StringBuffer without  the synchronized keyword.  Step 20: start thinking about architecture.
    </quote>

    In Java 5.0, Sun went and did this step for you.  They created StringBuilder that meets that exact requirement (unsynchronized version of StringBuffer).

    Funny thing is, any time you have code that looks like this:
    String name = lastname + ", " + firstname;

    javac actually generates this:
    String name = (new StringBuffer(lastname)).append(", ").append(firstname).toString();

    (replace "StingBuffer" with "StringBuilder") for Java 5.0+

    So.... your company was still using StringBuffer all over the place.

    I made a program to demonstrate that you were wrong. But, you know what?... you are damn right. :) I'm using jdk-1.5.0-fcs, in Resin 3.09 ( sorry, I'm not used to runnable Java ). It gives consistent results every time I run it.

    I check if Java uses StringBuiler when finding several string concatenated using the "+" operator on the same assignation.

    Loop 100 times. // trivial differences Time for s = s + "new"; 1 Time for s += "new"; 1 Time for s.append("new"); 0 Time for s = "new" + "new"; 0 Time for s = "new" + "new" + "new"; 1 Time for s = "new" + "new" + "new" ... (10 times); 108

    Loop 1000 times. //concatenating multiple strings is as fast as StringBuilder Time for s = s + "new"; 381 Time for s += "new"; 508 Time for s.append("new"); 1 Time for s = "new" + "new"; 1 Time for s = "new" + "new" + "new"; 1 Time for s = "new" + "new" + "new" ... (10 times); 1

    Loop 10000 times. //concatenating multiple strings is as fast as StringBuilder Time for s = s + "new"; 58532 Time for s += "new"; 67301 Time for s.append("new"); 124 Time for s = "new" + "new"; 232 Time for s = "new" + "new" + "new"; 130 Time for s = "new" + "new" + "new" ... (10 times); 231

    The code was this:

    final long times = 1000;
    long timesForThisLoop = 0;
    long startTime = 0;
    long finalTime = 0;
    double myNumber = 0;
    
    %>Loop <%=times%> times.
    <% startTime = System.currentTimeMillis(); String s1 = new String(""); timesForThisLoop = times; for (int j = 0; j < timesForThisLoop; j++) { s1 = s1 + String.valueOf(++myNumber) ; } finalTime = System.currentTimeMillis()-startTime; s1=null; %>Time for s = s + "new"; <%=finalTime%>
    <% out.flush(); startTime = System.currentTimeMillis(); String s2 = new String(""); timesForThisLoop = times; for (int j = 0; j < timesForThisLoop; j++) { s2 += String.valueOf(++myNumber) ; } finalTime = System.currentTimeMillis()-startTime; s2=null; %>Time for s += "new"; <%=finalTime%>
    <% out.flush(); startTime = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); timesForThisLoop = times; for (int j = 0; j < timesForThisLoop; j++) { sb.append(String.valueOf(++myNumber)); } finalTime = System.currentTimeMillis()-startTime; sb=null; %>Time for s.append("new"); <%=finalTime%>
    <% out.flush(); startTime = System.currentTimeMillis(); String s3 = new String(""); timesForThisLoop = times/2; for (int j = 0; j < timesForThisLoop; j++) { s3 = String.valueOf(++myNumber) + String.valueOf(++myNumber); } finalTime = System.currentTimeMillis()-startTime; s3=null; %> Time for s = "new" + "new"; <%=finalTime%>
    <% out.flush(); startTime = System.currentTimeMillis(); String s5 = new String(""); timesForThisLoop = times/3; for (int j = 0; j < timesForThisLoop; j++) { s5 = String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber); } finalTime = System.currentTimeMillis()-startTime; s5=null; %> Time for s = "new" + "new" + "new"; <%=finalTime%>
    <% out.flush(); startTime = System.currentTimeMillis(); String s4 = new String(""); timesForThisLoop = times/10; for (int j = 0; j < timesForThisLoop; j++) { s4 = String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber) + String.valueOf(++myNumber); } finalTime = System.currentTimeMillis()-startTime; s4=null; %> Time for s = "new" + "new" + "new" ... (10 times); <%=finalTime%>
    <% out.flush(); %>
  • Fred Flintstone (unregistered) in reply to Mike R
    Mike R:
    In regards to pre-vs post increment

    in the context of the for loop or any other "just increment the damn thing" situation, the resulting assembly code is identical:
    9:        ++i;
    0040102F   mov         eax,dword ptr [ebp-4]
    00401032   add         eax,1
    00401035   mov         dword ptr [ebp-4],eax
    10:       i++;
    00401038   mov         ecx,dword ptr [ebp-4]
    0040103B   add         ecx,1
    0040103E   mov         dword ptr [ebp-4],ecx


    code
    Since the code we are talking about is in Java, it might also help to look at the generated byte codes for such a loop:
      19:  iconst_0                             

    for (int i=0; i < 10; i++)  loop
      20:  istore_1
      21:  iload_1
      22:  bipush  10
      24:  if_icmpge       33
      27:  iinc    1, 1
      30:  goto    21

      33:  iconst_0                              for (int i=0; i < 10; ++i)  loop
      34:  istore_1
      35:  iload_1
      36:  bipush  10
      38:  if_icmpge       47
      41:  iinc    1, 1
      44:  goto    35
    [/code]
    They are identical here as well.

  • (cs) in reply to Enric Naval
    Loop 100 times. 
    // trivial differences 
    Time for s = s + "new"; 1 
    Time for s += "new"; 1 
    Time for s.append("new"); 0 
    Time for s = "new" + "new"; 0 
    Time for s = "new" + "new" + "new"; 1 
    Time for s = "new" + "new" + "new" ... (10 times); 108 
    
    Loop 1000 times. 
    //concatenating multiple strings is as fast as StringBuilder 
    Time for s = s + "new"; 381 
    Time for s += "new"; 508 
    Time for s.append("new"); 1 
    Time for s = "new" + "new"; 1 
    Time for s = "new" + "new" + "new"; 1 
    Time for s = "new" + "new" + "new" ... (10 times); 1 
    
    Loop 10000 times. 
    //concatenating multiple strings is as fast as StringBuilder 
    Time for s = s + "new"; 58532 
    Time for s += "new"; 67301 
    Time for s.append("new"); 124 
    Time for s = "new" + "new"; 232 
    Time for s = "new" + "new" + "new"; 130 
    Time for s = "new" + "new" + "new" ... (10 times); 231 
    

    and they say that coding HTML is easy :)

  • (cs) in reply to kipthegreat

    and the code was this:

    
    
    final long times = 1000; 
    long timesForThisLoop = 0;
    long startTime = 0;
    long finalTime = 0;
    double myNumber = 0;
    
    %>Loop <%=times%> times.<br><%
    
    
    String s1 = new String("");
    timesForThisLoop = times;
    startTime = System.currentTimeMillis();
    for (int j = 0; j < timesForThisLoop; j++) {
      s1 = s1 + String.valueOf(++myNumber) ;
    }
    finalTime = System.currentTimeMillis()-startTime;
    %>Time for s = s + "new"; <%=finalTime%><br> <%
    out.flush();
    
    
    String s2 = new String("");
    timesForThisLoop = times;
    startTime = System.currentTimeMillis();
    for (int j = 0; j < timesForThisLoop; j++) {
      s2 += String.valueOf(++myNumber)  ;
    }
    finalTime = System.currentTimeMillis()-startTime;
    %>Time for s += "new"; <%=finalTime%><br> <%
    out.flush();
    
    
    StringBuilder sb = new StringBuilder();
    timesForThisLoop = times;
    startTime = System.currentTimeMillis();
    for (int j = 0; j < timesForThisLoop; j++) {
      sb.append(String.valueOf(++myNumber));
    }
    finalTime = System.currentTimeMillis()-startTime;
    %>Time for s.append("new"); <%=finalTime%><br> <%
    out.flush();
    
    
    String s3 = new String("");
    timesForThisLoop = times/2;
    startTime = System.currentTimeMillis();
    for (int j = 0; j < timesForThisLoop; j++) {
      s3 = String.valueOf(++myNumber) + 
           String.valueOf(++myNumber);
    }
    finalTime = System.currentTimeMillis()-startTime;
    %>
    Time for s = "new" + "new"; <%=finalTime%><br>
    <%
    out.flush();
    
    startTime = System.currentTimeMillis();
    String s4 = new String("");
    timesForThisLoop = times/3;
    startTime = System.currentTimeMillis();
    for (int j = 0; j < timesForThisLoop; j++) {
      s4 = String.valueOf(++myNumber) + 
           String.valueOf(++myNumber) + 
           String.valueOf(++myNumber);
    }
    finalTime = System.currentTimeMillis()-startTime;
    %>
    Time for s = "new" + "new" + "new"; <%=finalTime%><br>
    <%
    out.flush();
    
    
    
    String s5 = new String("");
    timesForThisLoop = times/10;
    startTime = System.currentTimeMillis();
    for (int j = 0; j < timesForThisLoop; j++) {
      s5 = String.valueOf(++myNumber) + 
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber) +
           String.valueOf(++myNumber);
    }
    finalTime = System.currentTimeMillis()-startTime;
    %>
    Time for s = "new" + "new" + "new" ... (10 times); <%=finalTime%><br>
    <%
    out.flush();
    %>
    
    
  • (cs) in reply to dubwai
    dubwai:

    The cost of exceptions is built into all Python calls.  In Java, it's only costly if they are thrown.  So exceptions aren't free in Python anymore than heath care is free if you pay for insurance.

    Wrong, it's not and it's already been said. The call to "try" is just about free, but getting an exception actually thrown and catched costs a lot. What many people fail to grasp in the "It's easier to ask for forgiveness than permission" is that "asking for forgiveness" is not supposed to be the default baseline behaviour, it's supposed to be the rare once in a while one, if you get an exception thrown every pair of calls you're supposed to start checking beforehand instead of being stupid. If you get an exception every 10000 runs or something, the lone exception's overhead will be far under systematic pre-check.

    dubwai:
    Anonymous:

    It's blamed on the Java language because Java has the garbage collector, and it's supposed to free the objects.

    How do you free an object in Java?

    You don't.  The garbage collector does.

    Good coders will set their reference variables to "null" in order to dereference a pointer and ensure that the associated resources WILL be released at the next GC call, when they really mean to get an object freed.

  • (cs) in reply to masklinn
    masklinn:

    Good coders will set their reference variables to "null" in order to dereference a pointer and ensure that the associated resources WILL be released at the next GC call, when they really mean to get an object freed.



    I read that often, but if that was really necessary, the GC would not deserve its name. Face it: circular references occur very often in oo programming. For example, in a GUI, every component keeps a reference to its parent, which keeps a reference to a collection of its child, which keeps a reference to the component. You would have to do a lot of work to set all those references to null.
    Another thing is much more important regarding garbace collection: some objects, e.g. file handles, database connections, database statements record sets etc. keep limited external resources until garbage collection - which may or may not happen anytime soon - or explicitely closed using the close() (or whatever) method. For that reason, good coders use the close() method for these objects; in many cases, the right place to do so is the finally{} part of a try{}catch[} block.
  • (cs) in reply to Mung Kee
    Mung Kee:
    Your post is based largely on conjecture and/or ignorance

    Mike R:
    I have yet to see a well-performing Java application

    So they don't exist?


    They might exist, I just haven't seen one.


    Although the Windows PLAF in Swing is a bit awkward, download Eclipse (SWT) and tell me what doesn't "fit in."


    Why are there apps that still use swing? I think I have seen some of the SWT-based apps. (mainly in applets)


    Pointless, since it doesn't exist.  Besides, if you didn't drink the M$ kool-aid, you would be developing (nearly) platform independent C.


    I realise it technically doesn't exist, but then there is Managed C++ in .net (yeah, it's bastardised and MS, but potentially platform-independant w/o need to recompile.)

    More than just that. For console apps, fine. Just so long as you don't have any need to pay attention to memory alignment, word sizes, endianness, or theading, and use ANSI compliant compilers across the board. I know it can be done, but not easily for any non-trivial application. Aside from that, it must be compiled for each platform. GUI is another beast alltogether, becuase there is no "standard" GUI library to do cross-platform development, though I know several third party solutions exist.


    Of course it's easy to cast blame on the VM...when you're ignorant of it.


    Yes, and no. VM will always have some slowdown compared to native code. Even if that slowdown is only during the first encounter of a function, or translating to native machine code on first run.


    http://img.photobucket.com/albums/v84/wannabeshoes/KoolAidManII.jpg


    Heh.
  • (cs) in reply to Mike R

    Mike R:


    Yes, and no. VM will always have some slowdown compared to native code. Even if that slowdown is only during the first encounter of a function, or translating to native machine code on first run.

    That seems obvious but consider that the VM has information that compiler does not usually have: the exact hardware being used at runtime.  Also, you need to understand that the rigid structure of Java allows it to be optimized very effectively.

    Here's a fun fact that is not well known.  Object allocation on the heap in modern VMs is generally much cheaper than in C.  Generational GC allows the VM to keep the free heap sapce contiguous.  When it comes time to allocate, it doesn't have search through a fragmented heap.  Some people estimate that the overhead for Object allocation in Java is now around 10 machine instructions.

  • (cs) in reply to masklinn
    masklinn:
    Good coders will set their reference variables to "null" in order to dereference a pointer and ensure that the associated resources WILL be released at the next GC call, when they really mean to get an object freed.


    Actually the reason is not so much to free the object, but avoid memory leaks. Therefor good coders will use explicit null-assignments only within code of possibly long living objects. Examples (coded in "demo-mode"):

    <font style="color: rgb(169, 169, 169);" size="2">// a long living static array of objects
    static Object [] oa = new Object[1000];

    // the number of objects currently in the array
    int size = 0;

    // a method to remove the last object
    Object removeLast() {
      return oa[--size];
    }
    </font>
    Now what's wrong with this removeLast? Most certainly: the array still references the removed object. We rewrite:

    <font style="color: rgb(169, 169, 169);" size="2">// a method to remove the last object
    Object removeLast() {
      Object retval = oa[--size];
      oa[size] = null;
      return retval;
    }
    </font>
    Now similar to Collection#toArray() we have

    <font style="color: rgb(169, 169, 169);" size="2">// a method to return a copy of the array
    Object[] toArray() {
      Object[] retval = new Object[size];
      System.arrayCopy(oa,0,retval,0,size);
      return retval;
    }
    </font>
    and we use it in some code:

    <font style="color: rgb(169, 169, 169);" size="2">void someMethod() {
      Object[] oo = toArray();
      // do something with the array, e.g. reorder and print to stdout
    }
    </font>
    Now why is it not necessary to clear all references in "oo" as it was in removeLast() ?

    Answer: Because oo cannot be long living. No risk of memory leak. No need for null-assignment.

    Good coders know to distinguish between these cases. "Supposedly Good Coders" will do an unnecessary

    <font style="color: rgb(169, 169, 169);" size="2">for (int i = oo.length; i>0; oo[--i]=null);
    </font>
    and they will boast about how cleverly they have put this "GC-helping-code" into a single for statement.

    cu
  • (cs) in reply to masklinn
    masklinn:
    Good coders will set their reference variables to "null" in order to dereference a pointer and ensure that the associated resources WILL be released at the next GC call, when they really mean to get an object freed.

    Good coders usually don't worry about it.  Except in very specific circumstances, setting references to null is just making more work for yourself.
  • (cs) in reply to dubwai
    dubwai:

    Mike R:


    Yes, and no. VM will always have some slowdown compared to native code. Even if that slowdown is only during the first encounter of a function, or translating to native machine code on first run.

    That seems obvious but consider that the VM has information that compiler does not usually have: the exact hardware being used at runtime.  Also, you need to understand that the rigid structure of Java allows it to be optimized very effectively.


    But is it enough to counteract the initial delays? At least that means the VM can take advantage of MMX, SSE, SSE2, and the AMD equivalents, as well as 64-bit hardware. But, in order to detect where operations can be parallelized for these instructions takes a good bit of analysis (take a look at how long the Intel compiler takes when building with the optimisations turned on.). Unless I'm being naïve, it seems to me that the VM will need to do the same sorts of analysis, or it won't get nearly as optimal a result.


    Here's a fun fact that is not well known.  Object allocation on the heap in modern VMs is generally much cheaper than in C.  Generational GC allows the VM to keep the free heap sapce contiguous.  When it comes time to allocate, it doesn't have search through a fragmented heap.  Some people estimate that the overhead for Object allocation in Java is now around 10 machine instructions.

    This is good if you're creating and destroying objects on the heap constantly, and the size of those objects varies widely. Otherwise, if objects are close in size, the heap shouldn't have to search very far to find a place to allocate.

  • (cs) in reply to Mike R
    Mung Kee:

    Of course it's easy to cast blame on the VM...when you're ignorant of it.
    Mike R:

     Yes, and no. VM will always have some slowdown compared to native code. Even if that slowdown is only during the first encounter of a function, or translating to native machine code on first run.





    Many times, it's not about the speed of execution, but the speed of development.  When you need to deploy an application enterprise wide, on disparate systems, quickly, I'll pick Java 99 times out of 100.  (It's probably 100 out of 100, but I wanted the wiggle room :D)
  • (cs) in reply to Mike R
    Mike R:
    dubwai:

    Mike R:


    Yes, and no. VM will always have some slowdown compared to native code. Even if that slowdown is only during the first encounter of a function, or translating to native machine code on first run.

    That seems obvious but consider that the VM has information that compiler does not usually have: the exact hardware being used at runtime.  Also, you need to understand that the rigid structure of Java allows it to be optimized very effectively.


    But is it enough to counteract the initial delays? At least that means the VM can take advantage of MMX, SSE, SSE2, and the AMD equivalents, as well as 64-bit hardware. But, in order to detect where operations can be parallelized for these instructions takes a good bit of analysis (take a look at how long the Intel compiler takes when building with the optimisations turned on.). Unless I'm being naïve, it seems to me that the VM will need to do the same sorts of analysis, or it won't get nearly as optimal a result.

    The VM doesn't have to do this on every execution, though it may.  But it can do this on install or first execution.

    Your point is well taken, though.  It takes a while for the VM to 'warm up' and optimize, inline, and natively compile the code.  This is one reason that VMs do so poorly in short application benchmarks.  But for long running apps, it doesn't amount to much.


    Here's a fun fact that is not well known.  Object allocation on the heap in modern VMs is generally much cheaper than in C.  Generational GC allows the VM to keep the free heap sapce contiguous.  When it comes time to allocate, it doesn't have search through a fragmented heap.  Some people estimate that the overhead for Object allocation in Java is now around 10 machine instructions.

    This is good if you're creating and destroying objects on the heap constantly, and the size of those objects varies widely. Otherwise, if objects are close in size, the heap shouldn't have to search very far to find a place to allocate.

    It's possible that you work with different types of applications but I don't know of any that make sure that all their Objects are the same size.  I find it unlikely that it will just happen by chance.

  • (cs) in reply to Mung Kee

    From Mung Kee:
    You know you suck when your code relies on an Exception being thrown.  When exceptions become logic, don't they, by definition, cease to be exceptions?

    I've been attempting to use Excel/VBA lately. The only way to check whether, for example, a workbook is open (i.e. is a member of the Workbooks collection) is to try it and see if it breaks (as far as I can tell anyway).

    So, what would you do when your function may or may not be called after opening the workbook it references, and any attempt to open an already-opened workbook will result in a programmatically-untrappable error?

    Of course, that doesn't apply here, but your comment only applies in sufficiently well-written programming languages.

  • (cs) in reply to Corkscrew
    Corkscrew:
    From Mung Kee:
    You know you suck when your code relies on an Exception being thrown.  When exceptions become logic, don't they, by definition, cease to be exceptions?

    I've been attempting to use Excel/VBA lately. The only way to check whether, for example, a workbook is open (i.e. is a member of the Workbooks collection) is to try it and see if it breaks (as far as I can tell anyway).

    So, what would you do when your function may or may not be called after opening the workbook it references, and any attempt to open an already-opened workbook will result in a programmatically-untrappable error?

    Of course, that doesn't apply here, but your comment only applies in sufficiently well-written programming languages.

    If that's the only means to check, it's laughable.  I have never run into this situation in any of the languages I have worked with, let alone with a language that is constantly accused of using exceptions too liberally.  (my ignorance of it aside) If that's what you have to do with the Excel API for VBA, then that's what you have to do.  The example happens to be Java, and it's poor design here.  VBA may have a different take.
  • (cs) in reply to Corkscrew
    Corkscrew:
    I've been attempting to use Excel/VBA lately. The only way to check whether, for example, a workbook is open (i.e. is a member of the Workbooks collection) is to try it and see if it breaks (as far as I can tell anyway).


    Nonsense.  You can just walk the Workbooks collection and check the Filename property (don't recollect exactly what it's called), because Excel won't let you open two files of the same name (even if they're in different folders)
  • (cs) in reply to Chris F

    Chris F:
    masklinn:
    Good coders will set their reference variables to "null" in order to dereference a pointer and ensure that the associated resources WILL be released at the next GC call, when they really mean to get an object freed.

    Good coders usually don't worry about it.  Except in very specific circumstances, setting references to null is just making more work for yourself.

    Setting variables to null can actually make the GC job harder.

    http://www-128.ibm.com/developerworks/java/library/j-jtp01274.html#3.0

  • Bob (unregistered) in reply to brazzy

    This looks like a poor application of a useful mechanism. I've seen this used many times in J2ME code for cell phones and the first time I saw it elicited a "wtf?". However, when we benchmarked it on the target hardware, we found it significantly faster than testing a loop counter. It's possible that the code may also compile down smaller with an empty exception catch rather than a loop bounds check, but I haven't checked for definite.

    Of course, this was for running tight loops as fast as possible on extremely limited hardware + VM. This particular application doesn't seem to warrant this, and as people have pointed out, it's likely that this optimization actually performs slower due to the target VM.

    It's not necessarily a "WTF?", more of a "Why TF is this being used here?".

  • (cs) in reply to Mike R
    Mike R:
    Mung Kee:
    Your post is based largely on conjecture and/or ignorance

    Mike R:
    I have yet to see a well-performing Java application

    So they don't exist?


    They might exist, I just haven't seen one.

    There's a lot of really big webapps built in Java - and also lots of custom software. COTS software benefits little from platform independance, probably the reason why Java isn't very popular in that area.

    Mike R:


    Although the Windows PLAF in Swing is a bit awkward, download Eclipse (SWT) and tell me what doesn't "fit in."


    Why are there apps that still use swing? I think I have seen some of the SWT-based apps. (mainly in applets)


    Because swing is part of the Java API, and SWT isn't. You can use Swing everywhere there's an implementation of Java 1.2 or higher. For SWT, you need the SWT libraries (which are quite a chunk of code), which may not even exist for your platform (since it uses native widgets, SWT takes a lot of work to port).
  • (cs) in reply to ammoQ
    ammoQ:
    masklinn:

    Good coders will set their reference variables to "null" in order to dereference a pointer and ensure that the associated resources WILL be released at the next GC call, when they really mean to get an object freed.



    I read that often, but if that was really necessary, the GC would not deserve its name. Face it: circular references occur very often in oo programming. For example, in a GUI, every component keeps a reference to its parent, which keeps a reference to a collection of its child, which keeps a reference to the component. You would have to do a lot of work to set all those references to null.


    You don't have to set every reference to null, and circular references are no problem. The Java GC kills stuff that isn't reachable from the application anymore, including stuff in circular references when there's no reference from "outside" the circle.

    Setting stuff to null is rarely necessary because it usually goes out of scope anyway. There ARE some cases where you explicitly have to remove references to avoid hanging on to unneeded stuff and causing a memory leak. But usually that means removing some entry in a collection rather than setting a variable to null (well, implicitly it means a variable somewhere is set to null).

  • (cs) in reply to brazzy
    brazzy:
    There's a lot of really big webapps built in Java - and also lots of custom software. COTS software benefits little from platform independance, probably the reason why Java isn't very popular in that area.

    I just assumed he was referring to Swing, since it IS slow.  I don't know how anyone can difinitively say that one language performs better than another, for web applications.  If they do, it usually has quite a lot to do with devotion to their language of choice and misguided disdain for all others.  I think most of us will agree that to come to the conclusion that there aren't any well-performing Java applications simply because you haven't seen any is nothing more than conjecture.


  • (cs) in reply to brazzy

    brazzy:

    Mike R:


    Although the Windows PLAF in Swing is a bit awkward, download Eclipse (SWT) and tell me what doesn't "fit in."


    Why are there apps that still use swing? I think I have seen some of the SWT-based apps. (mainly in applets)


    Because swing is part of the Java API, and SWT isn't. You can use Swing everywhere there's an implementation of Java 1.2 or higher. For SWT, you need the SWT libraries (which are quite a chunk of code), which may not even exist for your platform (since it uses native widgets, SWT takes a lot of work to port).

    It's not that much code.  I just started playing around with it.  I only needed a 1MB jar a 300K dll for WinXP.

  • (cs) in reply to dubwai
    dubwai:

    The VM doesn't have to do this on every execution, though it may.  But it can do this on install or first execution.

    Your point is well taken, though.  It takes a while for the VM to 'warm up' and optimize, inline, and natively compile the code.  This is one reason that VMs do so poorly in short application benchmarks.  But for long running apps, it doesn't amount to much.


    think .NET is set up to do just this, compile itself to whatever the machine its running on on the first run. I don't know if Java does this or not.

    It's possible that you work with different types of applications but I don't know of any that make sure that all their Objects are the same size.  I find it unlikely that it will just happen by chance.



    I was working on a "Objects are supposed to be relatively compact" bent. That doesn't always pan out in the real world, though.
  • (cs) in reply to Mike R
    Mike R:
    think .NET is set up to do just this, compile itself to whatever the machine its running on on the first run. I don't know if Java does this or not.

    Making generalizations about JVMs is tough as there is no single vendor.  A lot of these things are "could do"s.  Each version of the Sun JVM has been significantly faster, from what I understand though.  They do implement a lot of these things.  One cool one in that article I posted is that the VM can recognize that an Object reference is never used outside the stack and can allocate it on the stack.  I'm wonder if that's been done.

    Mike R:

    I was working on a "Objects are supposed to be relatively compact" bent. That doesn't always pan out in the real world, though.

    Well, arrays kind of make that difficult, right?

Leave a comment on “Array of Hope”

Log In or post as a guest

Replying to comment #:

« Return to Article