001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.adaptive.measurements.organizers;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.adaptive.controller.Controller;
017    import org.jikesrvm.adaptive.database.methodsamples.MethodCountData;
018    import org.jikesrvm.adaptive.measurements.RuntimeMeasurements;
019    import org.jikesrvm.adaptive.measurements.listeners.MethodListener;
020    import org.jikesrvm.adaptive.util.AOSLogging;
021    import org.jikesrvm.scheduler.RVMThread;
022    import org.jikesrvm.scheduler.SystemThread;
023    import org.vmmagic.pragma.NonMoving;
024    
025    /**
026     * An organizer for method listener information that
027     * simply accumulates the samples into a private
028     * MethodCountData instance.
029     * <p>
030     * This organizer is used to simply gather aggregate sample data and
031     * report it.
032     */
033    @NonMoving
034    public final class AccumulatingMethodSampleOrganizer extends Organizer {
035    
036      private MethodCountData data;
037    
038      public AccumulatingMethodSampleOrganizer() {}
039    
040      /**
041       * Initialization: set up data structures and sampling objects.
042       * <p>
043       * Uses either timer based sampling or counter based sampling,
044       * depending on {@link Controller#options}.
045       */
046      @Override
047      public void initialize() {
048        data = new MethodCountData();
049        new AsyncReporter().start();
050        int numSamples = Controller.options.METHOD_SAMPLE_SIZE * RVMThread.availableProcessors;
051        if (Controller.options.mlCBS()) {
052          numSamples *= VM.CBSMethodSamplesPerTick;
053        }
054        MethodListener methodListener = new MethodListener(numSamples);
055        listener = methodListener;
056        listener.setOrganizer(this);
057        if (Controller.options.mlTimer()) {
058          RuntimeMeasurements.installTimerMethodListener(methodListener);
059        } else if (Controller.options.mlCBS()) {
060          RuntimeMeasurements.installCBSMethodListener(methodListener);
061        } else {
062          if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED, "Unexpected value of method_listener_trigger");
063        }
064      }
065    
066      @Override
067      void thresholdReached() {
068        AOSLogging.logger.organizerThresholdReached();
069        int numSamples = ((MethodListener) listener).getNumSamples();
070        int[] samples = ((MethodListener) listener).getSamples();
071        data.update(samples, numSamples);
072      }
073    
074      @Override
075      public void report() {
076        VM.sysWrite("\nMethod sampler report");
077        if (data != null) data.report();
078      }
079      @NonMoving
080      class AsyncReporter extends SystemThread {
081        public AsyncReporter() {
082          super("Async Profile Reporter");
083        }
084        @Override
085        public void run() {
086          for (;;) {
087            RVMThread.doProfileReport.waitAndCloseWithHandshake();
088            report();
089          }
090        }
091      }
092    }
093