add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / benchmark / src / java / org / apache / lucene / benchmark / byTask / tasks / PerfTask.java
1 package org.apache.lucene.benchmark.byTask.tasks;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import java.text.NumberFormat;
21
22 import org.apache.lucene.benchmark.byTask.PerfRunData;
23 import org.apache.lucene.benchmark.byTask.stats.Points;
24 import org.apache.lucene.benchmark.byTask.stats.TaskStats;
25 import org.apache.lucene.benchmark.byTask.utils.Config;
26
27 /**
28  * An abstract task to be tested for performance. <br>
29  * Every performance task extends this class, and provides its own
30  * {@link #doLogic()} method, which performs the actual task. <br>
31  * Tasks performing some work that should be measured for the task, can override
32  * {@link #setup()} and/or {@link #tearDown()} and place that work there. <br>
33  * Relevant properties: <code>task.max.depth.log</code>.<br>
34  * Also supports the following logging attributes:
35  * <ul>
36  * <li>log.step - specifies how often to log messages about the current running
37  * task. Default is 1000 {@link #doLogic()} invocations. Set to -1 to disable
38  * logging.
39  * <li>log.step.[class Task Name] - specifies the same as 'log.step', only for a
40  * particular task name. For example, log.step.AddDoc will be applied only for
41  * {@link AddDocTask}, but not for {@link DeleteDocTask}. It's a way to control
42  * per task logging settings. If you want to omit logging for any other task,
43  * include log.step=-1. The syntax is "log.step." together with the Task's
44  * 'short' name (i.e., without the 'Task' part).
45  * </ul>
46  */
47 public abstract class PerfTask implements Cloneable {
48
49   static final int DEFAULT_LOG_STEP = 1000;
50   
51   private PerfRunData runData;
52   
53   // propeties that all tasks have
54   private String name;
55   private int depth = 0;
56   protected int logStep;
57   private int logStepCount = 0;
58   private int maxDepthLogStart = 0;
59   private boolean disableCounting = false;
60   protected String params = null;
61
62   private boolean runInBackground;
63   private int deltaPri;
64
65   protected static final String NEW_LINE = System.getProperty("line.separator");
66
67   /** Should not be used externally */
68   private PerfTask() {
69     name = getClass().getSimpleName();
70     if (name.endsWith("Task")) {
71       name = name.substring(0, name.length() - 4);
72     }
73   }
74
75   public void setRunInBackground(int deltaPri) {
76     runInBackground = true;
77     this.deltaPri = deltaPri;
78   }
79
80   public boolean getRunInBackground() {
81     return runInBackground;
82   }
83
84   public int getBackgroundDeltaPriority() {
85     return deltaPri;
86   }
87
88   protected volatile boolean stopNow;
89
90   public void stopNow() {
91     stopNow = true;
92   }
93
94   public PerfTask(PerfRunData runData) {
95     this();
96     this.runData = runData;
97     Config config = runData.getConfig();
98     this.maxDepthLogStart = config.get("task.max.depth.log",0);
99
100     String logStepAtt = "log.step";
101     String taskLogStepAtt = "log.step." + name;
102     if (config.get(taskLogStepAtt, null) != null) {
103       logStepAtt = taskLogStepAtt;
104     }
105
106     // It's important to read this from Config, to support vals-by-round.
107     logStep = config.get(logStepAtt, DEFAULT_LOG_STEP);
108     // To avoid the check 'if (logStep > 0)' in tearDown(). This effectively
109     // turns logging off.
110     if (logStep <= 0) {
111       logStep = Integer.MAX_VALUE;
112     }
113   }
114   
115   @Override
116   protected Object clone() throws CloneNotSupportedException {
117     // tasks having non primitive data structures should override this.
118     // otherwise parallel running of a task sequence might not run correctly. 
119     return super.clone();
120   }
121
122   public void close() throws Exception {
123   }
124
125   /**
126    * Run the task, record statistics.
127    * @return number of work items done by this task.
128    */
129   public final int runAndMaybeStats(boolean reportStats) throws Exception {
130     if (!reportStats || shouldNotRecordStats()) {
131       setup();
132       int count = doLogic();
133       count = disableCounting ? 0 : count;
134       tearDown();
135       return count;
136     }
137     if (reportStats && depth <= maxDepthLogStart && !shouldNeverLogAtStart()) {
138       System.out.println("------------> starting task: " + getName());
139     }
140     setup();
141     Points pnts = runData.getPoints();
142     TaskStats ts = pnts.markTaskStart(this, runData.getConfig().getRoundNumber());
143     int count = doLogic();
144     count = disableCounting ? 0 : count;
145     pnts.markTaskEnd(ts, count);
146     tearDown();
147     return count;
148   }
149
150   /**
151    * Perform the task once (ignoring repetitions specification)
152    * Return number of work items done by this task.
153    * For indexing that can be number of docs added.
154    * For warming that can be number of scanned items, etc.
155    * @return number of work items done by this task.
156    */
157   public abstract int doLogic() throws Exception;
158   
159   /**
160    * @return Returns the name.
161    */
162   public String getName() {
163     if (params==null) {
164       return name;
165     } 
166     return new StringBuilder(name).append('(').append(params).append(')').toString();
167   }
168
169   /**
170    * @param name The name to set.
171    */
172   protected void setName(String name) {
173     this.name = name;
174   }
175
176   /**
177    * @return Returns the run data.
178    */
179   public PerfRunData getRunData() {
180     return runData;
181   }
182
183   /**
184    * @return Returns the depth.
185    */
186   public int getDepth() {
187     return depth;
188   }
189
190   /**
191    * @param depth The depth to set.
192    */
193   public void setDepth(int depth) {
194     this.depth = depth;
195   }
196   
197   // compute a blank string padding for printing this task indented by its depth  
198   String getPadding () {
199     char c[] = new char[4*getDepth()];
200     for (int i = 0; i < c.length; i++) c[i] = ' ';
201     return new String(c);
202   }
203   
204   /* (non-Javadoc)
205    * @see java.lang.Object#toString()
206    */
207   @Override
208   public String toString() {
209     String padd = getPadding();
210     StringBuilder sb = new StringBuilder(padd);
211     if (disableCounting) {
212       sb.append('-');
213     }
214     sb.append(getName());
215     if (getRunInBackground()) {
216       sb.append(" &");
217       int x = getBackgroundDeltaPriority();
218       if (x != 0) {
219         sb.append(x);
220       }
221     }
222     return sb.toString();
223   }
224
225   /**
226    * @return Returns the maxDepthLogStart.
227    */
228   int getMaxDepthLogStart() {
229     return maxDepthLogStart;
230   }
231
232   protected String getLogMessage(int recsCount) {
233     return "processed " + recsCount + " records";
234   }
235   
236   /**
237    * Tasks that should never log at start can override this.  
238    * @return true if this task should never log when it start.
239    */
240   protected boolean shouldNeverLogAtStart () {
241     return false;
242   }
243   
244   /**
245    * Tasks that should not record statistics can override this.  
246    * @return true if this task should never record its statistics.
247    */
248   protected boolean shouldNotRecordStats () {
249     return false;
250   }
251
252   /**
253    * Task setup work that should not be measured for that specific task.
254    * By default it does nothing, but tasks can implement this, moving work from 
255    * doLogic() to this method. Only the work done in doLogicis measured for this task.
256    * Notice that higher level (sequence) tasks containing this task would then 
257    * measure larger time than the sum of their contained tasks.
258    * @throws Exception 
259    */
260   public void setup () throws Exception {
261   }
262   
263   /**
264    * Task tearDown work that should not be measured for that specific task.
265    * By default it does nothing, but tasks can implement this, moving work from 
266    * doLogic() to this method. Only the work done in doLogicis measured for this task.
267    * Notice that higher level (sequence) tasks containing this task would then 
268    * measure larger time than the sum of their contained tasks.
269    */
270   public void tearDown() throws Exception {
271     if (++logStepCount % logStep == 0) {
272       double time = (System.currentTimeMillis() - runData.getStartTimeMillis()) / 1000.0;
273       NumberFormat nf = NumberFormat.getInstance();
274       nf.setMaximumFractionDigits(2);
275       System.out.println(nf.format(time) + " sec --> "
276           + Thread.currentThread().getName() + " " + getLogMessage(logStepCount));
277     }
278   }
279
280   /**
281    * Sub classes that supports parameters must override this method to return true.
282    * @return true iff this task supports command line params.
283    */
284   public boolean supportsParams () {
285     return false;
286   }
287   
288   /**
289    * Set the params of this task.
290    * @exception UnsupportedOperationException for tasks supporting command line parameters.
291    */
292   public void setParams(String params) {
293     if (!supportsParams()) {
294       throw new UnsupportedOperationException(getName()+" does not support command line parameters.");
295     }
296     this.params = params;
297   }
298   
299   /**
300    * @return Returns the Params.
301    */
302   public String getParams() {
303     return params;
304   }
305
306   /**
307    * Return true if counting is disabled for this task.
308    */
309   public boolean isDisableCounting() {
310     return disableCounting;
311   }
312
313   /**
314    * See {@link #isDisableCounting()}
315    */
316   public void setDisableCounting(boolean disableCounting) {
317     this.disableCounting = disableCounting;
318   }
319
320 }