Show running time at the end of process

edited September 2016 in How To...

Hi guys I need some help. I want to display the time an application has been running for at the end of a process how do I do this. Thank you in advance.

Answers

  • Returns the number of milliseconds (thousandths of a second) since starting the program. This information is often used for timing events and animation sequences.

    https://processing.org/reference/millis_.html

    So I will do:

    void setup(){size(100,500);}
    void draw(){}
    void MousePressed(){
      println("Exiting at " + millis/1000.0 + " seconds");
      exit();
    } 
    

    I hope this helps,

    Kf

  • Hello Kf. Thank you for your reply but I have not been able to get this to work. I added parenthesis to 'millis' and changed MousePressed to mousePressed

    void setup(){size(300,500);} void draw(){} void mousePressed (){ println("Exiting at " + millis()/1000 + " seconds"); }>

  • Answer ✓

    I am sorry, here is the corrected version. Millis is a function so I forgot the properly call it:

    void setup() {
      size(300, 500);
    }
    void draw() {
    }
    void mousePressed() {
      println("Exiting at " + millis()/1000.0 + " seconds");
      exit();
    } 
    

    Kf

  • End of a process or end of the main process(i.e. the application itself)?
    And I hope you need this only during troubleshooting phase of your project, because println() doesn't do anything useful if you use the executable exported by Processing.

  • siminan87, to follow up on kfrajer and Lord_of_the_Galaxy's comment:

    Calculating time and printing it to the console is easy. Displaying time on the screen before exiting can be a bit tricky. Logging exit time reliably can be extremely tricky -- especially if you can't trust your users to exit in the correct way, and are trying to handle multiple exit methods and conditions (press button, close window, select menu exit, etc. etc.), then it can all start to seem like black magic.

    If you just need a console log, do as kfrajer's post indicates above. If you need to display to screen before exit, or to write a log, etc. say more about what -- I have some detailed code examples on hand.

  • I found those notes, so I'm going to go ahead and post them here in case they are useful to anyone in the future.

    If you just need a console log...

    Do as in kfrajer's post above -- done.

    void draw() {}
    void keyPressed() {
      println("Exiting at " + millis()/1000.0 + " seconds");
      exit();
    } 
    

    If you need to display to the screen...

    Save your time to a variable -- then reveal a special message in the draw loop.

    /**
     * Display a screen timing message
     * 2016-08-06  Processing 3.2.1
     */
    float doneTime = 0;
    void draw() {
      background(192);
      translate(width/2,height/2);
      textAlign(CENTER,CENTER);
      if(doneTime = 0){
        text("Timing...\n" + millis()/1000, 0, 0);
      } else {
        text("Done at\n" + doneTime + " seconds", 0, 0);
      }  
    }
    void keyPressed() {  
      doneTime = millis()/1000.0;
      println("Done at " + doneTime + " seconds");
    } 
    

    QUIRK: Processing may take it a long time (even multiple seconds) to render your very first text() drawn to the screen (I believe can be due to lazy loading). If your sketch is already drawing text to the screen (as this example does) then this won't affect you. If the timing message is your first text however then the long delay for it to appear may be confusing. You can work around this by briefly loading text to the screen when your sketch starts.

    If you want to display to the screen BEFORE EXIT....

    You'll either need a two-stage exit with two inputs (first stop, then confirm exit) or you will want to wait so that the user has time to read the exit message on the screen before the window disappears. It is tempting to use delay(), however, this will prevent drawing the message to the screen on the next draw loop. However since we already have our exit time, an easy solution is to test if exiting is true and then run exit() 5 seconds later.

    /**
     * Display a screen exit timing message
     * 2016-08-06
     */
    boolean exiting = false;
    float exitTime = 0;
    void draw() {
      background(192);
      translate(width/2,height/2);
      textAlign(CENTER,CENTER);
      if(exiting==false){
        text("Timing...\n" + millis()/1000, 0, 0);
      } else {
        text("Exiting at\n" + exitTime + " seconds",0,0);
        if(exitTime + 5 < millis()/1000.0){
          exit();
        }
      }
    }  
    void keyPressed() {
      exitTime = millis()/1000.0;
      println("Exiting at " + exitTime + " seconds");
      exiting = true;   //// reveal screen exit message in draw loop
    }
    

    If you have more complicated things to do on exit then instead of an if in the draw loop you could use a thread() -- which allows screen drawing to continue, even if it uses delay() as a stopwatch timer. For example, add a thread call to your input check:

    thread("doExit");
    

    ...and have it call a doExit function, which waits, then closes the sketch. Drawing will continue while this function runs:

    void doExit(){
      delay(5000);
      exit();
    }
    

    If you need to log your final message and time to a file

    Try using createWriter() -- be sure to write, flush, close, THEN exit (see the example). If you might close unexpectedly and/or can't trust the user to quit correctly then you can write to your log file at periodic intervals rather than just once at the end.

    If you want your exit code to run in more varied situations

    Supposing that the users press ESC, or click window-close -- your exit code timing won't run. Fullscreen might be one way to encourage them. Overriding the default Processing quit key (ESC) might be another.

    void setup() {
      fullScreen(true);
    }
    void keyPressed{
      if(key=ESC){ exiting==true; } // override default exit();
    }
    

    If you want something to run reliably as the very last thing your sketch does

    At the point where we want something (like writing to a log file) to be the very last thing that a sketch does, and to happen no matter what and no matter how the sketch is stopped, then we start to get into dark arts... running code on exit can be hard to guarantee in Processing / Java. I believe that the currently recommended best way is to add a DisposeHandler, although I haven't done it myself -- you can find some good technical discussion of that here:

  • @jeremydouglass Why not just override the exit() method itself??

  • edited September 2016

    @Lord_of_the_Galaxy -- why not override exit()? Good question. I didn't include it only because I found old statements from Ben Fry saying "it should not be overridden."

    exit() is a different mechanism, that will handle calling stop(). it should not be overridden. exit() sets a flag that the app should quit the next time it's safe (as soon as the current setup() or draw() call finishes). Beta Forum

    The current exit() reference indicates that exit handles completing the draw loop -- which is important because "closing out an application while draw() is running may cause a crash (particularly with P3D)."

    Since you must always call super.exit anyway for safety....

    void exit() {
      //put code to run on exit here
      super.exit();
    }
    

    ...I just recommended a custom function instead, which is functionally equivalent:

    void doExit(){
      //put code to run on exit here
      exit();
    }
    
  • edited September 2016

    @jeremydouglass I am not an expert or something, but if I remember right, exit() method is the one that is called by the window's close button. So in order to make the code much simpler and prevent having to replace all exit() method calls with customExit(), this is by far the best:

    void exit() {
      //put code to run on exit here
      super.exit();
    }
    
  • edited September 2016

    @Lord_of_the_Galaxy -- Fair enough.

    When I tested exiting on Mac in the Processing 3.2.1 PDE environment with:

    1. the close window button
    2. Command-Q
    3. Command-W
    4. Menu > Quit
    5. an "exit()" call in a function

    ...then this executed the on-exit code correctly in all five situations:

    //// do something on exit
    void setup() {
      size(400, 400);
    }
    void draw() {
      if(millis()>10000){exit();}
    }
    void exit() {
      println("exiting");
      saveFrame("frame-######.png");
      super.exit();
    }
    

    So it appears to work well, and is a lot more elegant than writing a dispose handler. The only caveat is that old Fry quote saying exit() "should not be overridden" -- caveat lector etc.

  • I can see no problem with overriding exit() but you MUST call the super.exit() method at the end. If you don't the window disappears but the sketch is still running. I suspect this is why Ben discourages the practice but who knows.

    This takes a slightly different approach, try it out ...

    import javax.swing.*;
    
    void setup(){
      size(300,300);
    }
    
    void draw(){
      background(240);
      fill(0);
      text(millis(), 40,50);
    }
    
    void keyTyped(){
      if(key == 'q')
      exit();
    }
    
    void exit(){
      noLoop();
      surface.setVisible(false);
      showMessage("Execution time : " + millis()/1000 + " seconds", "Sketch terminated");  
      super.exit();
    }
    
    public void showMessage(String message, String title) {
      String m;
      if (platform == MACOSX) {
        m = PANE_TEXT_STYLE_MACOS.replaceAll("@@TITLE@@", title);
     //   title = "";
        m = m.replaceAll("@@MESSAGE@@", message);
      } else {
        m = PANE_TEXT_STYLE_OTHER.replaceAll("@@MESSAGE@@", message);
      }
      JOptionPane.showMessageDialog(null, m, title, JOptionPane.INFORMATION_MESSAGE);
    }
    
    final String PANE_TEXT_STYLE_MACOS = "<html> <head> <style type=\"text/css\">"+
      "b { font: 13pt \"Lucida Grande\" } p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
      "</style> </head> <b>@@TITLE@@</b> <p>@@MESSAGE@@</p>";
    
    final String PANE_TEXT_STYLE_OTHER = "<html> <head> <style type=\"text/css\">"+
      "b { font: 12pt \"Lucida Grande\" } p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
      "</style> </head> <b>@@MESSAGE@@ </b>";
    
  • edited September 2016

    Nice example!

    Given that overriding exit() seems reasonably robust, it would be very Processing-like (elegant, accessible) if users had a method that they could override to specify an exit event handler, just as they learn to use keyPressed() or mouseClicked() etc. - no worrying about super.exit() required.

    I'm imagining something like:

    1. P3's built-in exit() now first calls the empty method exitCalled() before continuing.
    2. The Processing reference describes the new exitCalled() as a place for users to put code that should run just before exit. It briefly outlines the conditions under which exitCalled() is expected to run, then cross-links it with the exit() reference.

    Thoughts on this enhancement idea?

  • PApplet already has a method exitCalled() so your pre-exit method would have to be named something else, perhaps preExit() ;) .

    It would be very easy to implement in the PApplet source code, just extra 2 lines of code and some comments. It would have the benefit of ensuring the exit() method is called at the correct time but give users the ability to do something before the application shuts done.

    Back to the original problem of showing the run time at the end of the sketch.

    The examples above that use println to display the time will work if the sketch is run from the PDE because it will show up in the Console pane but not it the sketch is an executable (i.e. has been exported). It does have the advantage the the process has actually stopped.

    My example has the advantage that it works with an exported sketch and the disadvantage in the the sketch hasn't stopped, I have simply made it invisible and stopped it looping.

    The true solution would be to launch another application on shutdown e.g.

    void exit(){
      String message ="Execution time : " + millis()/1000 + " seconds"; 
      // (executable file, actual parameters for executable) ??????
      PApplet.launch("absolute_path/filename", message);
      super.exit();
    }
    

    I haven't used the launch method before so I am not totally sure of how the parameters are used, but it will launch the executable and forget it so the last line will shutdown the original sketch.

  • @quark and @jeremydouglass about that launch method -
    It is fairly difficult to get it to work across multiple platforms(though the problem disappears when used with no arguments/parameters for executable) and make it work with a relative file path(for sharing with other computers), so I would certainly not recommend that.
    Besides that, always keep an error time of up to 1 second because of the simple fact you measure the time before you launched the other executable, so the time it took to launch it and the time it took it to fully close down the application are NOT counted.

  • A feature request for beforeExit() (or preExit, etc.) was submitted as Processing Issue 4714.

Sign In or Register to comment.