001/* An actor that consumes a specified amount of real time. 002 003 Copyright (c) 2008-2018 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.actor.lib; 029 030import ptolemy.data.BooleanToken; 031import ptolemy.data.LongToken; 032import ptolemy.data.Token; 033import ptolemy.data.expr.Parameter; 034import ptolemy.data.type.BaseType; 035import ptolemy.kernel.CompositeEntity; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.kernel.util.NameDuplicationException; 038 039/////////////////////////////////////////////////////////////////// 040//// ExecutionTime 041 042/** 043 Read the input token, if there is one, execute an (uninteresting) 044 computation to consume a specified amount of real time or to execute 045 it a fixed number of times, and produce 046 on the output the actual execution time (in milliseconds). Unlike the 047 Sleep actor, which suspends the calling thread for the specified 048 amount of time, this actor performs a computation during the 049 specified amount of time, thus consuming compute resources. 050 If <i>realTime</i> is true, then the number of computations it 051 performs is not fixed, but rather depends on what the thread 052 scheduler does. If it is false, then the amount of computation 053 done is fixed. The default is false. 054 055 @author Edward A. Lee 056 @version $Id$ 057 @since Ptolemy II 8.0 058 @see Sleep 059 @Pt.ProposedRating Yellow (eal) 060 @Pt.AcceptedRating Red (cxh) 061 */ 062public class ExecutionTime extends LimitedFiringSource { 063 064 /** Construct an actor with the given container and name. 065 * @param container The container. 066 * @param name The name of this actor. 067 * @exception IllegalActionException If the actor cannot be contained 068 * by the proposed container. 069 * @exception NameDuplicationException If the container already has an 070 * actor with this name. 071 */ 072 public ExecutionTime(CompositeEntity container, String name) 073 throws NameDuplicationException, IllegalActionException { 074 super(container, name); 075 executionTime = new Parameter(this, "executionTime"); 076 executionTime.setTypeEquals(BaseType.LONG); 077 executionTime.setExpression("1000L"); 078 079 realTime = new Parameter(this, "realTime"); 080 realTime.setTypeEquals(BaseType.BOOLEAN); 081 realTime.setExpression("false"); 082 083 granularity = new Parameter(this, "granularity"); 084 granularity.setTypeEquals(BaseType.LONG); 085 granularity.setExpression("400000L"); 086 087 output.setTypeEquals(BaseType.LONG); 088 089 // Show the firingCountLimit parameter last. 090 firingCountLimit.moveToLast(); 091 } 092 093 /////////////////////////////////////////////////////////////////// 094 //// parameters //// 095 096 /** The amount of time to consume. This is either in milliseconds, 097 * if the realTime parameter is set to true, or in the number of 098 * iterations of a fixed computation, if the realTime parameter 099 * is set to false. This is a long 100 * that defaults to 1000L. 101 */ 102 public Parameter executionTime; 103 104 /** The granularity of the computation. This parameter specifies 105 * the number of additions performed in each invocation of the 106 * (uninteresting) computation. This is a long, which defaults 107 * to 400000, which yields a computation time granularity 108 * of approximately 1msec on a MacBook Pro. 109 */ 110 public Parameter granularity; 111 112 /** If true, then the executionTime parameter is 113 * interpreted as milliseconds. If it is false (the default), then the 114 * executionTime parameter is interpreted to specify the number 115 * of cycles of a fixed computation. Use false to specify 116 * a fixed computational load, and use true to specify an 117 * amount of real time to consume. When this is true, 118 * if the thread executing the fire() method is preempted 119 * during its run, then less computation is done. 120 */ 121 public Parameter realTime; 122 123 /////////////////////////////////////////////////////////////////// 124 //// public methods //// 125 126 /** Read the input token, consume time, the produce on the 127 * output the actual execution time used. 128 * @exception IllegalActionException If send() throws it. 129 */ 130 @Override 131 public void fire() throws IllegalActionException { 132 long start = System.currentTimeMillis(); 133 super.fire(); 134 for (int i = 0; i < trigger.getWidth(); i++) { 135 if (trigger.hasToken(i)) { 136 // Read and discard the input. 137 trigger.get(i); 138 } 139 } 140 long executionTimeValue = ((LongToken) executionTime.getToken()) 141 .longValue(); 142 long granularityValue = ((LongToken) granularity.getToken()) 143 .longValue(); 144 boolean realTimeValue = ((BooleanToken) realTime.getToken()) 145 .booleanValue(); 146 boolean moreToDo = true; 147 long count = 0L; 148 int dummy = 0; 149 while (moreToDo) { 150 // NOTE: The number here determines the granularity. 151 for (int i = 0; i < granularityValue; i++) { 152 dummy++; 153 } 154 if (realTimeValue) { 155 moreToDo = System.currentTimeMillis() 156 - start < executionTimeValue; 157 } else { 158 moreToDo = count < executionTimeValue; 159 } 160 count++; 161 } 162 // To ensure that an optimizer does not optimize it away, print the 163 // dummy variable. 164 System.out.println("Fired ExecutionTime: " + dummy); 165 // Produce on the output the actual time consumed, in case because 166 // of the granularity above it differs from the specified time. 167 Token result = new LongToken(System.currentTimeMillis() - start); 168 output.send(0, result); 169 } 170}