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>


Reply via email to