Author: pmouawad
Date: Sun Feb 21 21:49:31 2016
New Revision: 1731570
URL: http://svn.apache.org/viewvc?rev=1731570&view=rev
Log:
Bug 59034 - Parallel downloads connection management is not realistic
Bugzilla Id: 59034
Modified:
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
jmeter/trunk/xdocs/changes.xml
Modified:
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
URL:
http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java?rev=1731570&r1=1731569&r2=1731570&view=diff
==============================================================================
---
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
(original)
+++
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
Sun Feb 21 21:49:31 2016
@@ -184,7 +184,7 @@ public class HTTPHC4Impl extends HTTPHCA
* 1 HttpClient instance per combination of (HttpClient,HttpClientKey)
*/
private static final ThreadLocal<Map<HttpClientKey, HttpClient>>
HTTPCLIENTS_CACHE_PER_THREAD_AND_HTTPCLIENTKEY =
- new ThreadLocal<Map<HttpClientKey, HttpClient>>(){
+ new InheritableThreadLocal<Map<HttpClientKey, HttpClient>>(){
@Override
protected Map<HttpClientKey, HttpClient> initialValue() {
return new HashMap<>();
@@ -702,7 +702,19 @@ public class HTTPHC4Impl extends HTTPHCA
if (resolver == null) {
resolver = SystemDefaultDnsResolver.INSTANCE;
}
- ClientConnectionManager connManager = new
MeasuringConnectionManager(createSchemeRegistry(), resolver);
+ MeasuringConnectionManager connManager = new
MeasuringConnectionManager(createSchemeRegistry(), resolver);
+
+ // Modern browsers use more connections per host than the current
httpclient default (2)
+ // when using parallel download the httpclient and connection
manager are shared by the downloads threads
+ // to be realistic JMeter must set an higher value to
DefaultMaxPerRoute
+ if(this.testElement.isConcurrentDwn()) {
+ try {
+ int maxConcurrentDownloads =
Integer.parseInt(this.testElement.getConcurrentPool());
+
connManager.setDefaultMaxPerRoute(Math.max(maxConcurrentDownloads,
connManager.getDefaultMaxPerRoute()));
+ } catch (NumberFormatException nfe) {
+ // no need to log -> will be done by the sampler
+ }
+ }
httpClient = new DefaultHttpClient(connManager, clientParams) {
@Override
Modified:
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
URL:
http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java?rev=1731570&r1=1731569&r2=1731570&view=diff
==============================================================================
---
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
(original)
+++
jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
Sun Feb 21 21:49:31 2016
@@ -1221,7 +1221,7 @@ public abstract class HTTPSamplerBase ex
res = container;
// Get the URL matcher
- String re=getEmbeddedUrlRE();
+ String re = getEmbeddedUrlRE();
Perl5Matcher localMatcher = null;
Pattern pattern = null;
if (re.length()>0){
@@ -1234,8 +1234,27 @@ public abstract class HTTPSamplerBase ex
}
// For concurrent get resources
- final List<Callable<AsynSamplerResultHolder>> liste = new
ArrayList<>();
+ final List<Callable<AsynSamplerResultHolder>> list = new
ArrayList<>();
+ int maxConcurrentDownloads = CONCURRENT_POOL_SIZE; // init with
default value
+ boolean isConcurrentDwn = isConcurrentDwn();
+ if(isConcurrentDwn) {
+
+ try {
+ maxConcurrentDownloads =
Integer.parseInt(getConcurrentPool());
+ } catch (NumberFormatException nfe) {
+ log.warn("Concurrent download resources selected, "//
$NON-NLS-1$
+ + "but pool size value is bad. Use default
value");// $NON-NLS-1$
+ }
+
+ // if the user choose a number of parallel downloads of 1
+ // no need to use another thread, do the sample on the current
thread
+ if(maxConcurrentDownloads == 1) {
+ log.warn("Number of parallel downloads set to 1, (sampler
name="+getName()+")");
+ isConcurrentDwn = false;
+ }
+ }
+
while (urls.hasNext()) {
Object binURL = urls.next(); // See catch clause below
try {
@@ -1265,9 +1284,9 @@ public abstract class HTTPSamplerBase ex
setParentSampleSuccess(res, false);
continue;
}
- if (isConcurrentDwn()) {
+ if (isConcurrentDwn) {
// if concurrent download emb. resources, add to a
list for async gets later
- liste.add(new ASyncSample(url, HTTPConstants.GET,
false, frameDepth + 1, getCookieManager(), this));
+ list.add(new ASyncSample(url, HTTPConstants.GET,
false, frameDepth + 1, getCookieManager(), this));
} else {
// default: serial download embedded resources
HTTPSampleResult binRes = sample(url,
HTTPConstants.GET, false, frameDepth + 1);
@@ -1281,20 +1300,15 @@ public abstract class HTTPSamplerBase ex
setParentSampleSuccess(res, false);
}
}
+
// IF for download concurrent embedded resources
- if (isConcurrentDwn()) {
- int poolSize = CONCURRENT_POOL_SIZE; // init with default value
- try {
- poolSize = Integer.parseInt(getConcurrentPool());
- } catch (NumberFormatException nfe) {
- log.warn("Concurrent download resources selected, "//
$NON-NLS-1$
- + "but pool size value is bad. Use default
value");// $NON-NLS-1$
- }
+ if (isConcurrentDwn && !list.isEmpty()) {
+
final String parentThreadName =
Thread.currentThread().getName();
// Thread pool Executor to get resources
// use a LinkedBlockingQueue, note: max pool size doesn't
effect
final ThreadPoolExecutor exec = new ThreadPoolExecutor(
- poolSize, poolSize, KEEPALIVETIME, TimeUnit.SECONDS,
+ maxConcurrentDownloads, maxConcurrentDownloads,
KEEPALIVETIME, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
new ThreadFactory() {
@Override
@@ -1318,7 +1332,7 @@ public abstract class HTTPSamplerBase ex
boolean tasksCompleted = false;
try {
// sample all resources with threadpool
- final List<Future<AsynSamplerResultHolder>> retExec =
exec.invokeAll(liste);
+ final List<Future<AsynSamplerResultHolder>> retExec =
exec.invokeAll(list);
// call normal shutdown (wait ending all tasks)
exec.shutdown();
// put a timeout if tasks couldn't terminate
@@ -1333,7 +1347,7 @@ public abstract class HTTPSamplerBase ex
CollectionProperty cookies =
binRes.getCookies();
for (JMeterProperty jMeterProperty : cookies) {
Cookie cookie = (Cookie)
jMeterProperty.getObjectValue();
- cookieManager.add(cookie) ;
+ cookieManager.add(cookie);
}
}
res.addSubResult(binRes.getResult());
@@ -1344,7 +1358,7 @@ public abstract class HTTPSamplerBase ex
}
tasksCompleted = exec.awaitTermination(1,
TimeUnit.MILLISECONDS); // did all the tasks finish?
} catch (InterruptedException ie) {
- log.warn("Interruped fetching embedded resources", ie); //
$NON-NLS-1$
+ log.warn("Interrupted fetching embedded resources", ie);
// $NON-NLS-1$
} catch (ExecutionException ee) {
log.warn("Execution issue when fetching embedded
resources", ee); // $NON-NLS-1$
} finally {
@@ -1964,7 +1978,6 @@ public abstract class HTTPSamplerBase ex
@Override
public AsynSamplerResultHolder call() {
JMeterContextService.replaceContext(jmeterContextOfParentThread);
- ((CleanerThread)
Thread.currentThread()).registerSamplerForEndNotification(sampler);
HTTPSampleResult httpSampleResult = sampler.sample(url, method,
areFollowingRedirect, depth);
if(sampler.getCookieManager() != null) {
CollectionProperty cookies =
sampler.getCookieManager().getCookies();
Modified: jmeter/trunk/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1731570&r1=1731569&r2=1731570&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Sun Feb 21 21:49:31 2016
@@ -115,6 +115,7 @@ Summary
<li><bug>59023</bug>HttpSampler UI : rework the embedded resources labels
and change default number of parallel downloads to 6. Contributed by Benoit
Wiart (benoit dot wiart at gmail.com)</li>
<li><bug>59028</bug>Use SystemDefaultDnsResolver singleton. Contributed by
Benoit Wiart (benoit dot wiart at gmail.com)</li>
<li><bug>59036</bug>FormCharSetFinder : Use JSoup instead of deprecated
HTMLParser</li>
+ <li><bug>59034</bug>Parallel downloads connection management is not
realistic. Contributed by Benoit Wiart (benoit dot wiart at gmail.com) and
Philippe Mouawad</li>
</ul>
<h3>Other samplers</h3>