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