Package org.eclipse.core.internal.runtime

Source Code of org.eclipse.core.internal.runtime.PerformanceStatsProcessor

/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.core.internal.runtime;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.PerformanceStats.PerformanceListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

/**
* Processes, records, and performs notification of performance events
* that occur in the system.
*/
public class PerformanceStatsProcessor extends Job {
  private static final PerformanceStatsProcessor instance = new PerformanceStatsProcessor();

  private static final long SCHEDULE_DELAY = 2000;

  /**
   * Events that have occurred but have not yet been broadcast.
   */
  private final ArrayList changes = new ArrayList();

  /**
   * Event failures that have occurred but have not yet been broadcast.
   * Maps (PerformanceStats -> Long).
   */
  private final HashMap failures = new HashMap();

  /**
   * Event listeners.
   */
  private final org.eclipse.core.runtime.ListenerList listeners = new org.eclipse.core.runtime.ListenerList();

  private PlatformLogWriter log;

  /*
   * @see PerformanceStats#addListener
   */
  public static void addListener(PerformanceListener listener) {
    instance.listeners.add(listener);
  }

  /**
   * Records the fact that an event occurred.
   *
   * @param stats The event that occurred
   */
  public static void changed(PerformanceStats stats) {
    synchronized (instance) {
      instance.changes.add(stats);
    }
    instance.schedule(SCHEDULE_DELAY);
  }

  /**
   * Records the fact that an event failed.
   *
   * @param stats The event that occurred
   * @param pluginId The id of the plugin that declared the blame object, or
   * <code>null</code>
   * @param elapsed The elapsed time for this failure
   */
  public static void failed(PerformanceStats stats, String pluginId, long elapsed) {
    synchronized (instance) {
      instance.failures.put(stats, new Long(elapsed));
    }
    instance.schedule(SCHEDULE_DELAY);
    instance.logFailure(stats, pluginId, elapsed);
  }

  /*
   * @see PerformanceStats#printStats(PrintWriter)
   */
  public static void printStats(PrintWriter out) {
    /* gather totals */
    long totalTime = 0;
    int totalCount = 0;
    PerformanceStats[] allStats = PerformanceStats.getAllStats();
    for (int i = 0; i < allStats.length; i++) {
      PerformanceStats stats = allStats[i];
      totalTime += stats.getRunningTime();
      totalCount += stats.getRunCount();
    }
    //dump stats
    out.println("---------------------------------------------------------------"); //$NON-NLS-1$
    for (int i = 0; i < allStats.length; i++) {
      PerformanceStats stats = allStats[i];
      out.print("Event: "); //$NON-NLS-1$
      out.print(stats.getEvent());
      out.print(" Blame: "); //$NON-NLS-1$
      out.print(stats.getBlameString());
      if (stats.getContext() != null) {
        out.print(" Context: "); //$NON-NLS-1$
        out.print(stats.getContext());
      }
      out.println();

      int runCount = stats.getRunCount();
      if (runCount > 0) {
        out.print("Run count: "); //$NON-NLS-1$
        out.print(Integer.toString(runCount));
        out.print(" ("); //$NON-NLS-1$
        out.print(Integer.toString((int) (runCount * 100.0 / totalCount)));
        out.println(" % of total)"); //$NON-NLS-1$
      }

      long runTime = stats.getRunningTime();
      if (runTime > 0) {
        out.print("Duration (ms): "); //$NON-NLS-1$
        out.print(Long.toString(runTime));
        out.print(" ("); //$NON-NLS-1$
        out.print(Integer.toString((int) (runTime * 100.0 / totalTime)));
        out.println(" % of total)"); //$NON-NLS-1$
      }
      out.println(""); //$NON-NLS-1$
    }
  }

  /*
   * @see PerformanceStats#removeListener
   */
  public static void removeListener(PerformanceListener listener) {
    instance.listeners.remove(listener);
  }

  /**
   * Private constructor to enforce singleton usage.
   */
  private PerformanceStatsProcessor() {
    super("Performance Stats"); //$NON-NLS-1$
    setSystem(true);
    setPriority(DECORATE);
    BundleContext context = PlatformActivator.getContext();
    String filter = '(' + FrameworkLog.SERVICE_PERFORMANCE + '=' + Boolean.TRUE.toString() + ')';
    ServiceReference[] references;
    FrameworkLog perfLog = null;
    try {
      references = context.getServiceReferences(FrameworkLog.class.getName(), filter);
      if (references != null && references.length > 0) {
        //just take the first matching service
        perfLog = (FrameworkLog) context.getService(references[0]);
        //make sure correct location is set
        IPath logLocation = Platform.getLogFileLocation();
        logLocation = logLocation.removeLastSegments(1).append("performance.log"); //$NON-NLS-1$
        perfLog.setFile(logLocation.toFile(), false);
      }
    } catch (Exception e) {
      IStatus error = new Status(IStatus.ERROR, Platform.PI_RUNTIME, 1, "Error loading performance log", e); //$NON-NLS-1$
      InternalPlatform.getDefault().log(error);
    }
    //use the platform log if we couldn't create the performance log
    if (perfLog == null)
      perfLog = InternalPlatform.getDefault().getFrameworkLog();
    log = new PlatformLogWriter(perfLog);
  }

  /**
   * Logs performance event failures to the platform's performance log
   */
  private void logFailure(PerformanceStats stats, String pluginId, long elapsed) {
    //may have failed to get the performance log service
    if (log == null)
      return;
    if (pluginId == null)
      pluginId = Platform.PI_RUNTIME;
    String msg = "Performance failure: " + stats.getEvent() + " blame: " + stats.getBlameString() + " context: " + stats.getContext() + " duration: " + elapsed; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
    log.logging(new Status(IStatus.WARNING, pluginId, 1, msg, new RuntimeException()), pluginId);
  }

  /*
   * @see Job#run(IProgressMonitor)
   */
  protected IStatus run(IProgressMonitor monitor) {
    PerformanceStats[] events;
    PerformanceStats[] failedEvents;
    Long[] failedTimes;
    synchronized (this) {
      events = (PerformanceStats[]) changes.toArray(new PerformanceStats[changes.size()]);
      changes.clear();
      failedEvents = (PerformanceStats[]) failures.keySet().toArray(new PerformanceStats[failures.size()]);
      failedTimes = (Long[]) failures.values().toArray(new Long[failures.size()]);
      failures.clear();
    }

    //notify performance listeners
    Object[] toNotify = listeners.getListeners();
    for (int i = 0; i < toNotify.length; i++) {
      final PerformanceStats.PerformanceListener listener = ((PerformanceStats.PerformanceListener) toNotify[i]);
      if (events.length > 0)
        listener.eventsOccurred(events);
      for (int j = 0; j < failedEvents.length; j++)
        listener.eventFailed(failedEvents[j], failedTimes[j].longValue());
    }
    schedule(SCHEDULE_DELAY);
    return Status.OK_STATUS;
  }

  /*
   * @see Job#shouldRun()
   */
  public boolean shouldRun() {
    return !changes.isEmpty() || !failures.isEmpty();
  }
}
TOP

Related Classes of org.eclipse.core.internal.runtime.PerformanceStatsProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.