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