Author: sebb
Date: Fri Sep 23 18:47:11 2011
New Revision: 1174950
URL: http://svn.apache.org/viewvc?rev=1174950&view=rev
Log:
Added AsynchSampleSender which sends samples from server to client
asynchronously.
Added:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/AsynchSampleSender.java
(with props)
Modified:
jakarta/jmeter/trunk/bin/jmeter.properties
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSenderFactory.java
jakarta/jmeter/trunk/xdocs/changes.xml
jakarta/jmeter/trunk/xdocs/usermanual/remote-test.xml
Modified: jakarta/jmeter/trunk/bin/jmeter.properties
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/bin/jmeter.properties?rev=1174950&r1=1174949&r2=1174950&view=diff
==============================================================================
--- jakarta/jmeter/trunk/bin/jmeter.properties (original)
+++ jakarta/jmeter/trunk/bin/jmeter.properties Fri Sep 23 18:47:11 2011
@@ -517,10 +517,10 @@ wmlParser.types=text/vnd.wap.wml
#---------------------------------------------------------------------------
# Remote batching support
-# default is Standard, which returns each sample
+# default is Standard, which returns each sample synchronously
# Hold retains samples until end of test (may need lots of memory)
# Batch returns samples in batches
-# Statistical returns sample stats
+# Statistical returns sample summary statistics
# hold_samples was originally defined as a separate property,
# but can now also be defined using mode=Hold
# mode can also be the class name of an implementation of
org.apache.jmeter.samplers.SampleSender
@@ -535,6 +535,11 @@ wmlParser.types=text/vnd.wap.wml
#mode=org.example.load.MySampleSender
#hold_samples=true
#num_sample_threshold=100
+# Asynchronous sender; uses a queue and background worker process to return
the samples
+#mode=Asynch
+# default queue size
+#asynch.batch.queue.size=20
+#
#
# Value is in milliseconds
#time_threshold=60000
Added:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/AsynchSampleSender.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/AsynchSampleSender.java?rev=1174950&view=auto
==============================================================================
---
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/AsynchSampleSender.java
(added)
+++
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/AsynchSampleSender.java
Fri Sep 23 18:47:11 2011
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.jmeter.samplers;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.jorphan.util.JMeterError;
+import org.apache.log.Logger;
+
+public class AsynchSampleSender implements SampleSender, Serializable {
+
+ private static final long serialVersionUID = 251L;
+
+ private static final Logger log = LoggingManager.getLoggerForClass();
+
+ // Create unique object as marker for end of queue
+ private transient static final SampleEvent FINAL_EVENT = new SampleEvent();
+
+ // created by client
+ private final RemoteSampleListener listener;
+
+ static {
+ log.info("Using Asynch Remote Sampler for this test run");
+ }
+
+ final int capacity = JMeterUtils.getPropDefault("asynch.batch.queue.size",
20); // $NON-NLS-1$
+
+ private transient BlockingQueue<SampleEvent> queue; // created by server
in readResolve method
+
+ private transient long queueWaits; // how many times we had to wait to
queue a sample
+
+ private transient long queueWaitTime; // how long we had to wait
(nanoSeconds)
+
+ /**
+ * Processed by the RMI server code.
+ * @throws ObjectStreamException
+ */
+ private Object readResolve() throws ObjectStreamException{
+ log.debug("Using batch queue size (asynch.batch.queue.size): " +
capacity);
+ queue = new ArrayBlockingQueue<SampleEvent>(capacity);
+ Worker worker = new Worker(queue, listener);
+ worker.setDaemon(true);
+ worker.start();
+ return this;
+ }
+
+ /**
+ * @deprecated only for use by test code
+ */
+ @Deprecated
+ public AsynchSampleSender(){
+ log.warn("Constructor only intended for use in testing"); //
$NON-NLS-1$
+ listener = null;
+ }
+
+ // Created by SampleSenderFactory
+ protected AsynchSampleSender(RemoteSampleListener listener) {
+ this.listener = listener;
+ }
+
+ public void testEnded() { // probably not used in server mode
+ log.debug("Test ended()");
+ try {
+ listener.testEnded();
+ } catch (RemoteException ex) {
+ log.warn("testEnded()"+ex);
+ }
+ }
+
+ public void testEnded(String host) {
+ log.debug("Test Ended on " + host);
+ try {
+ listener.testEnded(host);
+ queue.put(FINAL_EVENT);
+ } catch (Exception ex) {
+ log.warn("testEnded(host)"+ex);
+ }
+ if (queueWaits > 0) {
+ log.info("QueueWaits: "+queueWaits+"; QueueWaitTime:
"+queueWaitTime+" (nanoseconds)");
+ }
+ }
+
+ public void sampleOccurred(SampleEvent e) {
+ try {
+ if (!queue.offer(e)){ // we failed to add the element first time
+ queueWaits++;
+ long t1 = System.nanoTime();
+ queue.put(e);
+ long t2 = System.nanoTime();
+ queueWaitTime += t2-t1;
+ }
+ } catch (Exception err) {
+ log.error("sampleOccurred; failed to queue the sample", err);
+ }
+ }
+
+ private static class Worker extends Thread {
+
+ private final BlockingQueue<SampleEvent> queue;
+
+ private final RemoteSampleListener listener;
+
+ private Worker(BlockingQueue<SampleEvent> q, RemoteSampleListener l){
+ queue = q;
+ listener = l;
+ }
+
+ @Override
+ public void run() {
+ try {
+ boolean eof = false;
+ while (!eof) {
+ List<SampleEvent> l = new ArrayList<SampleEvent>();
+ SampleEvent e = queue.take();
+ while (!(eof = (e == FINAL_EVENT)) && e != null) { // try
to process as many as possible
+ l.add(e);
+ e = queue.poll(); // returns null if nothing on queue
currently
+ }
+ int size = l.size();
+ if (size > 0) {
+ try {
+ listener.processBatch(l);
+ } catch (RemoteException err) {
+ if (err.getCause() instanceof
java.net.ConnectException){
+ throw new JMeterError("Could not return
sample",err);
+ }
+ log.error("Failed to return sample", err);
+ }
+ }
+ }
+ } catch (InterruptedException e) {
+ }
+ log.debug("Worker ended");
+ }
+ }
+}
Propchange:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/AsynchSampleSender.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/AsynchSampleSender.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Modified:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSenderFactory.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSenderFactory.java?rev=1174950&r1=1174949&r2=1174950&view=diff
==============================================================================
---
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSenderFactory.java
(original)
+++
jakarta/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleSenderFactory.java
Fri Sep 23 18:47:11 2011
@@ -40,6 +40,8 @@ public class SampleSenderFactory {
private static final String MODE_STRIPPED_BATCH = "StrippedBatch"; //
$NON-NLS-1$
+ private static final String MODE_ASYNCH = "Asynch"; // $NON-NLS-1$
+
// Support original property name
private static final boolean holdSamples =
JMeterUtils.getPropDefault("hold_samples", false); // $NON-NLS-1$
@@ -70,6 +72,8 @@ public class SampleSenderFactory {
return new DataStrippingSampleSender(new
BatchSampleSender(listener));
} else if(type.equalsIgnoreCase(MODE_STRIPPED)){
return new DataStrippingSampleSender(listener);
+ } else if(type.equalsIgnoreCase(MODE_ASYNCH)){
+ return new AsynchSampleSender(listener);
} else {
// should be a user provided class name
SampleSender s = null;
Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=1174950&r1=1174949&r2=1174950&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Fri Sep 23 18:47:11 2011
@@ -185,6 +185,7 @@ httpclient3.retrycount=3
<h3>General</h3>
<ul>
<li>Bug 51822 - (part 1) save 1 invocation of GuiPackage#getCurrentGui</li>
+<li>Added AsynchSampleSender which sends samples from server to client
asynchronously.</li>
</ul>
<h2>Non-functional changes</h2>
Modified: jakarta/jmeter/trunk/xdocs/usermanual/remote-test.xml
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/remote-test.xml?rev=1174950&r1=1174949&r2=1174950&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/remote-test.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/remote-test.xml Fri Sep 23 18:47:11
2011
@@ -213,18 +213,21 @@ The chosen port will be logged in the se
</p>
</subsection>
-<subsection name="§-num;.4 Using sample batching" anchor="batchmode">
+<subsection name="§-num;.4 Using a different sample sender"
anchor="sendermode">
<p>
Listeners in the test plan send their results back to the client JMeter which
writes the results to the specified files
-By default, samples are sent back as they are generated. This can place a
large load on the network and the JMeter client.
+By default, samples are sent back synchronously as they are generated.
+This can affect the maximum throughput of the server test; the sample result
has to be sent back before the thread can
+continue.
There are some JMeter properties that can be set to alter this behaviour.
</p>
<ul>
-<li>mode - sample sending mode - default is Standard</li>
+<li>mode - sample sending mode - default is Standard. This should be set on
the client node.</li>
<ul>
- <li>Standard - send samples as soon as they are generated</li>
+ <li>Standard - send samples synchronously as soon as they are
generated</li>
<li>Hold - hold samples in an array until the end of a run. This may use a
lot of memory on the server.</li>
- <li>Batch - send saved samples when either the count or time exceeds a
threshold</li>
+ <li>Batch - send saved samples when either the count or time exceeds a
threshold,
+ at which point the samples are sent synchronously. See also the Asynch
mode, described below.</li>
<li>Statistical - send a summary sample when either the count or time
exceeds a threshold.
The samples are summarised by thread group name and sample label.
The following fields are accumulated:
@@ -239,6 +242,14 @@ There are some JMeter properties that ca
</li>
<li>Stripped - remove responseData from succesful samples</li>
<li>StrippedBatch - remove responseData from succesful samples, and send
as batches</li>
+ <li>Asynch - samples are temporarily stored in a local queue. A separate
worker thread sends the samples.
+ This allows the test thread to continue without waiting for the result
to be sent back to the client.
+ However, if samples are being created faster than they can be sent,
the queue will eventually fill up,
+ and the sampler thread will block until some samples can be drained
from the queue.
+ This mode is useful for smoothing out peaks in sample generation.
+ The queue size can be adjusted by setting the JMeter property
+ <b><code>asynch.batch.queue.size</code></b> (default 20) on the client
node.
+ </li>
<li>Custom implementation : set the mode parameter to your custom sample
sender class name.
This must implement the interface SampleSender and have a constructor
which takes a single
parameter of type RemoteSampleListener.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]