de.tudarmstadt.ukp.dkpro.core.performance.Stopwatch.java Source code

Java tutorial

Introduction

Here is the source code for de.tudarmstadt.ukp.dkpro.core.performance.Stopwatch.java

Source

/*
 * Copyright 2012
 * Ubiquitous Knowledge Processing (UKP) Lab
 * Technische Universitt Darmstadt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.tudarmstadt.ukp.dkpro.core.performance;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
import org.apache.uima.fit.descriptor.ConfigurationParameter;
import org.apache.uima.fit.descriptor.TypeCapability;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;

import de.tudarmstadt.ukp.dkpro.core.performance.type.TimerAnnotation;

/**
 * Can be used to measure how long the processing between two points in a pipeline takes.
 * For that purpose, the AE needs to be added two times, before and after the part of the pipeline that should be measured.
 */

@TypeCapability(inputs = { "de.tudarmstadt.ukp.dkpro.core.type.TimerAnnotation" }, outputs = {
        "de.tudarmstadt.ukp.dkpro.core.type.TimerAnnotation" })

public class Stopwatch extends JCasAnnotator_ImplBase {

    private Boolean isDownstreamTimer;
    private JCas jcas;;

    public static final String KEY_MEAN = "mean";
    public static final String KEY_SUM = "sum";
    public static final String KEY_STDDEV = "stddev";

    public static final String PARAM_TIMER_NAME = "timerName";
    /**
     * Name of the timer pair.
     * Upstream and downstream timer need to use the same name.
     */
    @ConfigurationParameter(name = PARAM_TIMER_NAME, mandatory = true)
    private String timerName;

    public static final String PARAM_OUTPUT_FILE = "timerOutputFile";
    /**
     * Name of the timer pair.
     * Upstream and downstream timer need to use the same name.
     */
    @ConfigurationParameter(name = PARAM_OUTPUT_FILE, mandatory = false)
    private File outputFile;

    private List<Long> times;

    @Override
    public void initialize(UimaContext context) throws ResourceInitializationException {
        super.initialize(context);

        times = new ArrayList<Long>();

        isDownstreamTimer = null;
    }

    @Override
    public void process(JCas jcas) throws AnalysisEngineProcessException {
        this.jcas = jcas;

        long currentTime = System.currentTimeMillis();

        if (isDownstreamTimer()) {
            TimerAnnotation timerAnno = JCasUtil.selectSingle(jcas, TimerAnnotation.class);
            timerAnno.setEndTime(currentTime);

            long startTime = timerAnno.getStartTime();

            times.add(currentTime - startTime);
        } else {
            TimerAnnotation timerAnno = new TimerAnnotation(jcas);
            timerAnno.setName(timerName);
            timerAnno.setStartTime(currentTime);
            timerAnno.addToIndexes();
        }
    }

    @Override
    public void collectionProcessComplete() throws AnalysisEngineProcessException {
        super.collectionProcessComplete();

        if (isDownstreamTimer()) {
            getLogger().info("Results from Timer '" + timerName + "' after processing all documents.");

            DescriptiveStatistics statTimes = new DescriptiveStatistics();
            for (Long timeValue : times) {
                statTimes.addValue((double) timeValue / 1000);
            }
            double sum = statTimes.getSum();
            double mean = statTimes.getMean();
            double stddev = statTimes.getStandardDeviation();

            StringBuilder sb = new StringBuilder();
            sb.append("Estimate after processing " + times.size() + " documents.");
            sb.append("\n");

            Formatter formatter = new Formatter(sb, Locale.US);

            formatter.format("Aggregated time: %,.1fs\n", sum);
            formatter.format("Time / Document: %,.3fs (%,.3fs)\n", mean, stddev);

            formatter.close();

            getLogger().info(sb.toString());

            if (outputFile != null) {
                try {
                    Properties props = new Properties();
                    props.setProperty(KEY_SUM, "" + sum);
                    props.setProperty(KEY_MEAN, "" + mean);
                    props.setProperty(KEY_STDDEV, "" + stddev);
                    OutputStream out = new FileOutputStream(outputFile);
                    props.store(out, "timer " + timerName + " result file");
                } catch (FileNotFoundException e) {
                    throw new AnalysisEngineProcessException(e);
                } catch (IOException e) {
                    throw new AnalysisEngineProcessException(e);
                }
            }
        }
    }

    private boolean isDownstreamTimer() {

        if (isDownstreamTimer == null) {
            // this is only a downstream timer if there already is a timer annotation with the same name
            for (TimerAnnotation timer : JCasUtil.select(jcas, TimerAnnotation.class)) {
                if (timer.getName().equals(timerName)) {
                    isDownstreamTimer = true;
                }
            }
        }

        if (isDownstreamTimer == null) {
            isDownstreamTimer = false;
        }

        return isDownstreamTimer;
    }
}