/* * Copyright 2007 Sun Microsystems, Inc. * * This file is part of jVoiceBridge. * * jVoiceBridge is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation and distributed hereunder * to you. * * jVoiceBridge is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Sun designates this particular file as subject to the "Classpath" * exception as provided by Sun in the License file that accompanied this * code. */ package com.sun.voip; public class TickerBusyWait implements Ticker { private String id; private int timePeriod; private long startTime; private int count; private int overSlept; private int underSlept; private int minDrift; private int maxDrift; private int totalDrift; private long lastTime; private int[] waitDistribution = new int[200]; private int totalWaitTime = 0; private boolean armed; public TickerBusyWait(String id) { this.id = id; } public void arm(long delay, long timePeriod) { this.timePeriod = (int) timePeriod; startTime = System.currentTimeMillis(); lastTime = startTime; minDrift = 0; maxDrift = 0; totalDrift = 0; count = 0; armed = true; } public void disarm() { armed = false; } public void tick() throws TickerException { if (!armed) { throw new TickerException(id + " not armed"); } long start = System.currentTimeMillis(); int drift = getDrift(); totalDrift += drift; if (drift > maxDrift) { maxDrift = drift; } if (drift < minDrift) { minDrift = drift; } count++; if (Logger.logLevel == -99) { Logger.println("drift " + drift); Logger.logLevel = 3; } if (drift > timePeriod) { overSlept++; return; } else if (drift < -timePeriod) { underSlept++; } do { drift = getDrift(); while ((int) (System.currentTimeMillis() - lastTime) < timePeriod) { Thread.yield(); } } while (drift < -timePeriod); updateWaitDistribution(start); } private int getDrift() { int actualElapsed = (int) (System.currentTimeMillis() - startTime); int expectedElapsed = count * timePeriod; return actualElapsed - expectedElapsed; } public int getMinDrift() { return minDrift; } public int getMaxDrift() { return maxDrift; } private void updateWaitDistribution(long start) { int elapsed = (int) (System.currentTimeMillis() - start); if (elapsed < 0) { elapsed = 0; } else if (elapsed >= waitDistribution.length) { elapsed = waitDistribution.length - 1; } waitDistribution[elapsed]++; totalWaitTime += elapsed; } public double getAvg() { return ((double)(System.currentTimeMillis() - startTime)) / count; } public void printStatistics() { if (count > 0) { Logger.println(id + " average time between ticks " + ((float)(System.currentTimeMillis() - startTime) / (float)count) + " ms"); if (Logger.logLevel >= Logger.LOG_INFO) { Logger.println("Total calls to TickerBusyWait " + count); Logger.println("OverSlept count " + overSlept); Logger.println("UnderSlept count " + underSlept); Logger.println("Minimum drift " + getMinDrift()); Logger.println("Maximum drift " + getMaxDrift()); Logger.println("Average drift " + (totalDrift / count)); Logger.println(""); Logger.println(id + " Wait time distribution"); Logger.println(id + " ms\tCount"); for (int i = 0; i < waitDistribution.length; i++) { if (waitDistribution[i] != 0) { Logger.println(id + " " + i + "\t" + waitDistribution[i]); } } Logger.println(""); } } } public static void main(String args[]) { TickerBusyWait tickerBusyWait = new TickerBusyWait("Test"); tickerBusyWait.arm(RtpPacket.PACKET_PERIOD, RtpPacket.PACKET_PERIOD); while (true) { try { tickerBusyWait.tick(); } catch (TickerException e) { System.out.println("tick() failed! " + e.getMessage()); System.exit(1); } Logger.println(" avg " + tickerBusyWait.getAvg()); } } }