001 /*
002 * Java Genetic Algorithm Library (jenetics-1.5.0).
003 * Copyright (c) 2007-2013 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.util;
021
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static org.jenetics.util.object.eq;
025 import static org.jenetics.util.object.hashCodeOf;
026
027 import java.io.Serializable;
028
029 import javax.measure.Measurable;
030 import javax.measure.Measure;
031 import javax.measure.quantity.Duration;
032 import javax.measure.unit.SI;
033
034 import javolution.lang.Reusable;
035
036 /**
037 * Timer for measure the performance of the GA. The timer uses nano second
038 * precision (by using {@link System#nanoTime()}). This timer is not synchronized.
039 * It's up to the user to ensure thread safety.
040 *
041 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
042 * @since 1.0
043 * @version 1.0 — <em>$Date: 2013-09-01 $</em>
044 */
045 public final class Timer
046 implements
047 Comparable<Timer>,
048 Reusable,
049 Serializable,
050 Cloneable
051 {
052 private static final long serialVersionUID = 1L;
053 private static final String DEFAULT_LABEL = "Timer";
054
055 private String _label;
056 /*private[test]*/ long _start = 0;
057 /*private[test]*/ long _stop = 0;
058 /*private[test]*/ long _sum = 0;
059
060 private transient Accumulator<? super Long> _accumulator = accumulators.NULL;
061
062 /**
063 * Create a new time with the given label. The label is use in the
064 * {@link #toString()} method.
065 *
066 * @param label the timer label.
067 * @throws NullPointerException if the {@code label} is {@code null}.
068 */
069 public Timer(final String label) {
070 _label = requireNonNull(label, "Time label");
071 }
072
073 /**
074 * Create a new Timer object.
075 */
076 public Timer() {
077 this(DEFAULT_LABEL);
078 }
079
080 /**
081 * Set the accumulator for the interim results.
082 *
083 * [code]
084 * final Mean<Long> variance = new Mean<>();
085 * final Timer timer = new Timer();
086 * timer.setAccumulator(variance);
087 *
088 * for (int i = 0; i < 100; ++I) {
089 * timer.start();
090 * ... // Do some measurable task.
091 * timer.stop();
092 * }
093 *
094 * // Print the average time used for the 'measurable' task.
095 * System.out.println(mean.getMean());
096 * [/code]
097 *
098 * @param accumulator the accumulator used for the interim results.
099 * @throws NullPointerException if the {@code accumulator} is {@code null}.
100 */
101 public void setAccumulator(final Accumulator<? super Long> accumulator) {
102 _accumulator = requireNonNull(accumulator, "Accumulator");
103 }
104
105 /**
106 * Start the timer.
107 */
108 public void start() {
109 _start = System.nanoTime();
110 }
111
112 /**
113 * Stop the timer.
114 */
115 public void stop() {
116 _stop = System.nanoTime();
117 final long time = _stop - _start;
118 _accumulator.accumulate(time);
119 _sum += time;
120 }
121
122 /**
123 * Reset the timer.
124 */
125 @Override
126 public void reset() {
127 _sum = 0;
128 _start = 0;
129 _stop = 0;
130 }
131
132 /**
133 * Return the overall time of this timer. The following code snippet would
134 * return a measured time of 10 s (theoretically).
135 * [code]
136 * final Timer timer = new Timer();
137 * for (int i = 0; i < 10; ++i) {
138 * timer.start();
139 * Thread.sleep(1000);
140 * timer.stop();
141 * }
142 * [/code]
143 *
144 * @return the measured time so far.
145 */
146 public Measurable<Duration> getTime() {
147 return Measure.valueOf(_sum, SI.NANO(SI.SECOND));
148 }
149
150 /**
151 * Return the time between two successive calls of {@link #start()} and
152 * {@link #stop()}.
153 *
154 * @return the interim time measured.
155 */
156 public Measurable<Duration> getInterimTime() {
157 return Measure.valueOf(_stop - _start, SI.NANO(SI.SECOND));
158 }
159
160 /**
161 * Return the timer label.
162 *
163 * @return the timer label.
164 */
165 public String getLabel() {
166 return _label;
167 }
168
169 /**
170 * Set the timer label.
171 *
172 * @param label the new timer label
173 */
174 public void setLabel(final String label) {
175 _label = requireNonNull(label, "Timer label");
176 }
177
178 @Override
179 public int compareTo(final Timer timer) {
180 requireNonNull(timer, "Timer");
181
182 long diff = _sum - timer._sum;
183 int comp = 0;
184 if (diff < 0) {
185 comp = -1;
186 } else if (diff > 0) {
187 comp = 1;
188 }
189 return comp;
190 }
191
192 @Override
193 public int hashCode() {
194 return hashCodeOf(getClass()).
195 and(_label).
196 and(_start).
197 and(_stop).
198 and(_sum).value();
199 }
200
201 @Override
202 public boolean equals(final Object object) {
203 if (object == this) {
204 return true;
205 }
206 if (!(object instanceof Timer)) {
207 return false;
208 }
209
210 final Timer timer = (Timer)object;
211 return eq(_start, timer._start) &&
212 eq(_stop, timer._stop) &&
213 eq(_sum, timer._sum) &&
214 eq(_label, timer._label);
215 }
216
217 @Override
218 public Timer clone() {
219 try {
220 return (Timer)super.clone();
221 } catch (CloneNotSupportedException e) {
222 throw new AssertionError(e);
223 }
224 }
225
226 @Override
227 public String toString() {
228 return format(
229 "%s: %11.11f s", _label,
230 getTime().doubleValue(SI.SECOND)
231 );
232 }
233
234 }
235
236
|