You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2011/11/24 22:37:07 UTC

svn commit: r1205987 - /jmeter/trunk/src/components/org/apache/jmeter/timers/SyncTimer.java

Author: pmouawad
Date: Thu Nov 24 21:37:06 2011
New Revision: 1205987

URL: http://svn.apache.org/viewvc?rev=1205987&view=rev
Log:
Bug 52183 - SyncTimer could be improved (performance+reliability)

Modified:
    jmeter/trunk/src/components/org/apache/jmeter/timers/SyncTimer.java

Modified: jmeter/trunk/src/components/org/apache/jmeter/timers/SyncTimer.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/timers/SyncTimer.java?rev=1205987&r1=1205986&r2=1205987&view=diff
==============================================================================
--- jmeter/trunk/src/components/org/apache/jmeter/timers/SyncTimer.java (original)
+++ jmeter/trunk/src/components/org/apache/jmeter/timers/SyncTimer.java Thu Nov 24 21:37:06 2011
@@ -19,14 +19,14 @@
 package org.apache.jmeter.timers;
 
 import java.io.Serializable;
+import java.util.concurrent.BrokenBarrierException;
 
 import org.apache.jmeter.engine.event.LoopIterationEvent;
 import org.apache.jmeter.testbeans.TestBean;
 import org.apache.jmeter.testelement.AbstractTestElement;
 import org.apache.jmeter.testelement.TestListener;
+import org.apache.jmeter.testelement.ThreadListener;
 import org.apache.jmeter.threads.JMeterContextService;
-import org.apache.jorphan.logging.LoggingManager;
-import org.apache.log.Logger;
 
 /**
  * The purpose of the SyncTimer is to block threads until X number of threads
@@ -34,21 +34,16 @@ import org.apache.log.Logger;
  * thus create large instant loads at various points of the test plan.
  *
  */
-public class SyncTimer extends AbstractTestElement implements Timer, Serializable, TestBean, TestListener {
+public class SyncTimer extends AbstractTestElement implements Timer, Serializable, TestBean, TestListener, ThreadListener {
     private static final long serialVersionUID = 2;
-
-    private static final Logger log = LoggingManager.getLoggerForClass();
-
-    // Must be an Object so it will be shared between threads
-    private int[] timerCounter = new int[] { 0 };
-
-    private transient Object sync = new Object();
+    
+    private BarrierWrapper barrier;
 
     private int groupSize;
 
     // Ensure transient object is created by the server
     private Object readResolve(){
-        sync = new Object();
+    	createBarrier();
         return this;
     }
 
@@ -71,26 +66,20 @@ public class SyncTimer extends AbstractT
      * {@inheritDoc}
      */
     public long delay() {
-        synchronized (sync) {
-            timerCounter[0]++;
-            final int groupSz = getGroupSize();
-            final int count = timerCounter[0];
-            if (
-                (groupSz == 0 && count >= // count of threads in the thread group
-                    JMeterContextService.getContext().getThreadGroup().getNumThreads())
-                ||
-                (groupSz > 0 && count >= groupSz)
-                ) {
-                sync.notifyAll();
-                timerCounter[0]=0; // reset counter once we have reached the limit
-            } else {
-                try {
-                    sync.wait();
-                } catch (InterruptedException e) {
-                    log.warn(e.getLocalizedMessage());
-                }
-            }
-        }
+    	if(getGroupSize()>=0) {
+    		int arrival = 0;
+    		try {
+				arrival = this.barrier.await();
+			} catch (InterruptedException e) {
+				return 0;
+			} catch (BrokenBarrierException e) {
+				return 0;
+			} finally {
+				if(arrival == 0) {
+					barrier.reset();
+				}
+			}
+    	}
         return 0;
     }
 
@@ -102,43 +91,66 @@ public class SyncTimer extends AbstractT
     @Override
     public Object clone() {
         SyncTimer newTimer = (SyncTimer) super.clone();
-        newTimer.timerCounter = timerCounter;
-        newTimer.sync = sync;
+        newTimer.barrier = barrier;
         return newTimer;
     }
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public void testStarted() {
-		testStarted(null);
-	}
+    /**
+     * {@inheritDoc}
+     */
+    public void testEnded() {
+        this.testEnded(null);        
+    }
 
-	/**
-	 * Reset timerCounter
-	 */
-	public void testStarted(String host) {
-		this.timerCounter[0] = 0;
-	}
+    /**
+     * Reset timerCounter
+     */
+    public void testEnded(String host) {
+    	createBarrier();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void testStarted() {
+        testStarted(null);
+    }
 
+    /**
+     * Reset timerCounter
+     */
+    public void testStarted(String host) {
+        createBarrier();
+    }
+
+	@Override
+	public void testIterationStart(LoopIterationEvent event) {
+		// NOOP
+	}
+	
 	/**
-	 * {@inheritDoc}
+	 * 
 	 */
-	public void testEnded() {
-		this.testEnded(null); 
+	private void createBarrier() {
+		if(getGroupSize() == 0) {
+			// Lazy init 
+			this.barrier = new BarrierWrapper();
+        } else {
+        	this.barrier = new BarrierWrapper(getGroupSize());
+        }
 	}
 
-	/**
-	 * Reset timerCounter
-	 */
-	public void testEnded(String host) {
-		 this.timerCounter[0] = 0;
+	@Override
+	public void threadStarted() {
+		int numThreadsInGroup = JMeterContextService.getContext().getThreadGroup().getNumThreads();
+		if(getGroupSize() == 0) {
+			// Unique Barrier creation ensured by synchronized setup
+			this.barrier.setup(numThreadsInGroup);
+        }
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public void testIterationStart(LoopIterationEvent event) {
+	@Override
+	public void threadFinished() {
 		// NOOP
 	}
 }
\ No newline at end of file