1 package org.apache.lucene.benchmark.byTask.utils;
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 import java.io.StreamTokenizer;
21 import java.io.StringReader;
22 import java.lang.reflect.Constructor;
23 import java.util.ArrayList;
24 import java.util.Arrays;
26 import org.apache.lucene.benchmark.byTask.PerfRunData;
27 import org.apache.lucene.benchmark.byTask.tasks.PerfTask;
28 import org.apache.lucene.benchmark.byTask.tasks.RepSumByPrefTask;
29 import org.apache.lucene.benchmark.byTask.tasks.TaskSequence;
32 * Test algorithm, as read from file
34 public class Algorithm {
36 private TaskSequence sequence;
37 private final String[] taskPackages;
40 * Read algorithm from file
41 * Property examined: alt.tasks.packages == comma separated list of
42 * alternate package names where tasks would be searched for, when not found
43 * in the default package (that of {@link PerfTask}{@link #getClass()}).
44 * If the same task class appears in more than one package, the package
45 * indicated first in this list will be used.
46 * @param runData perf-run-data used at running the tasks.
47 * @throws Exception if errors while parsing the algorithm
49 @SuppressWarnings("fallthrough")
50 public Algorithm (PerfRunData runData) throws Exception {
51 Config config = runData.getConfig();
52 taskPackages = initTasksPackages(config);
53 String algTxt = config.getAlgorithmText();
54 sequence = new TaskSequence(runData,null,null,false);
55 TaskSequence currSequence = sequence;
56 PerfTask prevTask = null;
57 StreamTokenizer stok = new StreamTokenizer(new StringReader(algTxt));
58 stok.commentChar('#');
59 stok.eolIsSignificant(false);
60 stok.ordinaryChar('"');
61 stok.ordinaryChar('/');
62 stok.ordinaryChar('(');
63 stok.ordinaryChar(')');
64 boolean colonOk = false;
65 boolean isDisableCountNextTask = false; // only for primitive tasks
66 currSequence.setDepth(0);
68 while (stok.nextToken() != StreamTokenizer.TT_EOF) {
71 case StreamTokenizer.TT_WORD:
73 Constructor<? extends PerfTask> cnstr = taskClass(config,s)
74 .asSubclass(PerfTask.class).getConstructor(PerfRunData.class);
75 PerfTask task = cnstr.newInstance(runData);
76 task.setDisableCounting(isDisableCountNextTask);
77 isDisableCountNextTask = false;
78 currSequence.addTask(task);
79 if (task instanceof RepSumByPrefTask) {
81 String prefix = stok.sval;
82 if (prefix==null || prefix.length()==0) {
83 throw new Exception("named report prefix problem - "+stok.toString());
85 ((RepSumByPrefTask) task).setPrefix(prefix);
87 // check for task param: '(' someParam ')'
89 if (stok.ttype!='(') {
92 // get params, for tasks that supports them, - anything until next ')'
93 StringBuilder params = new StringBuilder();
95 while (stok.ttype!=')') {
97 case StreamTokenizer.TT_NUMBER:
98 params.append(stok.nval);
100 case StreamTokenizer.TT_WORD:
101 params.append(stok.sval);
103 case StreamTokenizer.TT_EOF:
104 throw new Exception("unexpexted EOF: - "+stok.toString());
106 params.append((char)stok.ttype);
110 String prm = params.toString().trim();
111 if (prm.length()>0) {
116 // ---------------------------------------
117 colonOk = false; prevTask = task;
121 char c = (char)stok.ttype;
126 if (!colonOk) throw new Exception("colon unexpexted: - "+stok.toString());
128 // get repetitions number
130 if ((char)stok.ttype == '*') {
131 ((TaskSequence)prevTask).setRepetitions(TaskSequence.REPEAT_EXHAUST);
133 if (stok.ttype!=StreamTokenizer.TT_NUMBER) {
134 throw new Exception("expected repetitions number or XXXs: - "+stok.toString());
136 double num = stok.nval;
138 if (stok.ttype == StreamTokenizer.TT_WORD && stok.sval.equals("s")) {
139 ((TaskSequence) prevTask).setRunTime(num);
142 ((TaskSequence) prevTask).setRepetitions((int) num);
146 // check for rate specification (ops/min)
148 if (stok.ttype!=':') {
153 if (stok.ttype!=StreamTokenizer.TT_NUMBER) throw new Exception("expected rate number: - "+stok.toString());
154 // check for unit - min or sec, sec is default
156 if (stok.ttype!='/') {
158 ((TaskSequence)prevTask).setRate((int)stok.nval,false); // set rate per sec
161 if (stok.ttype!=StreamTokenizer.TT_WORD) throw new Exception("expected rate unit: 'min' or 'sec' - "+stok.toString());
162 String unit = stok.sval.toLowerCase();
163 if ("min".equals(unit)) {
164 ((TaskSequence)prevTask).setRate((int)stok.nval,true); // set rate per min
165 } else if ("sec".equals(unit)) {
166 ((TaskSequence)prevTask).setRate((int)stok.nval,false); // set rate per sec
168 throw new Exception("expected rate unit: 'min' or 'sec' - "+stok.toString());
178 // check for sequence name
181 if (stok.ttype!='"') {
187 if (stok.ttype!='"' || name==null || name.length()==0) {
188 throw new Exception("sequence name problem - "+stok.toString());
191 // start the sequence
192 TaskSequence seq2 = new TaskSequence(runData, name, currSequence, c=='[');
193 currSequence.addTask(seq2);
199 if (currSequence.isParallel()) {
200 throw new Exception("Can only create background tasks within a serial task");
204 if (stok.ttype != StreamTokenizer.TT_NUMBER) {
209 deltaPri = (int) stok.nval;
212 if (prevTask == null) {
213 throw new Exception("& was unexpected");
214 } else if (prevTask.getRunInBackground()) {
215 throw new Exception("double & was unexpected");
217 prevTask.setRunInBackground(deltaPri);
222 currSequence.setNoChildReport(); /* intentional fallthrough */
226 colonOk = true; prevTask = currSequence;
227 currSequence = currSequence.getParent();
231 isDisableCountNextTask = true;
237 } //switch(stok.ttype)
241 if (sequence != currSequence) {
242 throw new Exception("Unmatched sequences");
245 // remove redundant top level enclosing sequences
246 while (sequence.isCollapsable() && sequence.getRepetitions()==1 && sequence.getRate()==0) {
247 ArrayList<PerfTask> t = sequence.getTasks();
248 if (t!=null && t.size()==1) {
249 PerfTask p = t.get(0);
250 if (p instanceof TaskSequence) {
251 sequence = (TaskSequence) p;
259 private String[] initTasksPackages(Config config) {
260 String alts = config.get("alt.tasks.packages", null);
261 String dfltPkg = PerfTask.class.getPackage().getName();
263 return new String[]{ dfltPkg };
265 ArrayList<String> pkgs = new ArrayList<String>();
267 for (String alt : alts.split(",")) {
270 return pkgs.toArray(new String[0]);
273 private Class<?> taskClass(Config config, String taskName)
274 throws ClassNotFoundException {
275 for (String pkg : taskPackages) {
277 return Class.forName(pkg+'.'+taskName+"Task");
278 } catch (ClassNotFoundException e) {
279 // failed in this package, might succeed in the next one...
282 // can only get here if failed to instantiate
283 throw new ClassNotFoundException(taskName+" not found in packages "+Arrays.toString(taskPackages));
287 public String toString() {
288 String newline = System.getProperty("line.separator");
289 StringBuilder sb = new StringBuilder();
290 sb.append(sequence.toString());
292 return sb.toString();
296 * Execute this algorithm
299 public void execute() throws Exception {
301 sequence.runAndMaybeStats(true);
308 * Expert: for test purposes, return all tasks participating in this algorithm.
309 * @return all tasks participating in this algorithm.
311 public ArrayList<PerfTask> extractTasks() {
312 ArrayList<PerfTask> res = new ArrayList<PerfTask>();
313 extractTasks(res, sequence);
316 private void extractTasks (ArrayList<PerfTask> extrct, TaskSequence seq) {
320 ArrayList<PerfTask> t = sequence.getTasks();
323 for (final PerfTask p : t) {
324 if (p instanceof TaskSequence) {
325 extractTasks(extrct, (TaskSequence)p);