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 2012/12/09 00:23:04 UTC

svn commit: r1418783 - in /jmeter/trunk/src/core/org/apache/jmeter: samplers/SampleResult.java threads/JMeterContext.java threads/JMeterThread.java

Author: pmouawad
Date: Sat Dec  8 23:23:03 2012
New Revision: 1418783

URL: http://svn.apache.org/viewvc?rev=1418783&view=rev
Log:
Bug 54268 - Improve memory and CPU usage
Improve CPU by caching response as String instead of computing it for each post processor
Improve memory by eagerly cleaning the cached field
Bugzilla Id: 54268

Modified:
    jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
    jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
    jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java

Modified: jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java?rev=1418783&r1=1418782&r2=1418783&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java Sat Dec  8 23:23:03 2012
@@ -245,6 +245,11 @@ public class SampleResult implements Ser
     
     final long nanoThreadSleep;
     
+    /**
+     * Cache for responseData as string to avoid multiple computations
+     */
+    private String responseDataAsString;
+    
     private long initOffset(){
         if (useNanoTime){
             return nanoThreadSleep > 0 ? NanoOffset.getNanoOffset() : System.currentTimeMillis() - sampleNsClockInMs();
@@ -298,6 +303,7 @@ public class SampleResult implements Ser
         requestHeaders = res.requestHeaders;//OK
         responseCode = res.responseCode;//OK
         responseData = res.responseData;//OK
+        responseDataAsString = null;
         responseHeaders = res.responseHeaders;//OK
         responseMessage = res.responseMessage;//OK
         // Don't copy this; it is per instance resultFileName = res.resultFileName;
@@ -617,6 +623,7 @@ public class SampleResult implements Ser
      *            the new responseData value
      */
     public void setResponseData(byte[] response) {
+        responseDataAsString = null;
         responseData = response == null ? EMPTY_BA : response;
     }
 
@@ -631,6 +638,7 @@ public class SampleResult implements Ser
      */
     @Deprecated
     public void setResponseData(String response) {
+        responseDataAsString = null;
         try {
             responseData = response.getBytes(getDataEncodingWithDefault());
         } catch (UnsupportedEncodingException e) {
@@ -647,6 +655,7 @@ public class SampleResult implements Ser
      *
      */
     public void setResponseData(final String response, final String encoding) {
+        responseDataAsString = null;
         String encodeUsing = encoding != null? encoding : DEFAULT_CHARSET;
         try {
             responseData = response.getBytes(encodeUsing);
@@ -680,7 +689,10 @@ public class SampleResult implements Ser
      */
     public String getResponseDataAsString() {
         try {
-            return new String(responseData,getDataEncodingWithDefault());
+            if(responseDataAsString == null) {
+                responseDataAsString= new String(responseData,getDataEncodingWithDefault());
+            }
+            return responseDataAsString;
         } catch (UnsupportedEncodingException e) {
             log.warn("Using platform default as "+getDataEncodingWithDefault()+" caused "+e);
             return new String(responseData); // N.B. default charset is used deliberately here
@@ -1322,4 +1334,11 @@ public class SampleResult implements Ser
     public void setStartNextThreadLoop(boolean startNextThreadLoop) {
         this.startNextThreadLoop = startNextThreadLoop;
     }
+
+    /**
+     * Clean up cached data
+     */
+    public void cleanAfterSample() {
+        this.responseDataAsString = null;
+    }
 }

Modified: jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java?rev=1418783&r1=1418782&r2=1418783&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java Sat Dec  8 23:23:03 2012
@@ -205,4 +205,13 @@ public class JMeterContext {
     public boolean isRestartNextLoop() {
         return restartNextLoop;
     }
+
+    /**
+     * Clean cached data after sample
+     */
+    public void cleanAfterSample() {
+        if(previousResult != null) {
+            previousResult.cleanAfterSample();
+        }
+    }
 }

Modified: jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java?rev=1418783&r1=1418782&r2=1418783&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java Sat Dec  8 23:23:03 2012
@@ -254,6 +254,7 @@ public class JMeterThread implements Run
                 Sampler sam = controller.next();
                 while (running && sam != null) {
                 	process_sampler(sam, null, threadContext);
+                	threadContext.cleanAfterSample();
                 	if(onErrorStartNextLoop || threadContext.isRestartNextLoop()) {
                 	    if(threadContext.isRestartNextLoop()) {
                             triggerEndOfLoopOnParentControllers(sam, threadContext);



Re: svn commit: r1418783 - in /jmeter/trunk/src/core/org/apache/jmeter: samplers/SampleResult.java threads/JMeterContext.java threads/JMeterThread.java

Posted by Philippe Mouawad <ph...@gmail.com>.
I changed it to what you proposed.
Don't think it can be accessed from multiple thread except for Parallel
downloads maybe.

On Mon, Dec 10, 2012 at 3:21 PM, sebb <se...@gmail.com> wrote:

> On 8 December 2012 23:23,  <pm...@apache.org> wrote:
> > Author: pmouawad
> > Date: Sat Dec  8 23:23:03 2012
> > New Revision: 1418783
> >
> > URL: http://svn.apache.org/viewvc?rev=1418783&view=rev
> > Log:
> > Bug 54268 - Improve memory and CPU usage
> > Improve CPU by caching response as String instead of computing it for
> each post processor
> > Improve memory by eagerly cleaning the cached field
> > Bugzilla Id: 54268
> >
> > Modified:
> >     jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
> >     jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
> >     jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
> >
> > Modified:
> jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
> > URL:
> http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java?rev=1418783&r1=1418782&r2=1418783&view=diff
> >
> ==============================================================================
> > --- jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
> (original)
> > +++ jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
> Sat Dec  8 23:23:03 2012
> > @@ -245,6 +245,11 @@ public class SampleResult implements Ser
> >
> >      final long nanoThreadSleep;
> >
> > +    /**
> > +     * Cache for responseData as string to avoid multiple computations
> > +     */
> > +    private String responseDataAsString;
> > +
>
> Should probably be transient.
>
> Does it also need to be volatile? i.e. is it access from multiple threads?
>
> >      private long initOffset(){
> >          if (useNanoTime){
> >              return nanoThreadSleep > 0 ? NanoOffset.getNanoOffset() :
> System.currentTimeMillis() - sampleNsClockInMs();
> > @@ -298,6 +303,7 @@ public class SampleResult implements Ser
> >          requestHeaders = res.requestHeaders;//OK
> >          responseCode = res.responseCode;//OK
> >          responseData = res.responseData;//OK
> > +        responseDataAsString = null;
> >          responseHeaders = res.responseHeaders;//OK
> >          responseMessage = res.responseMessage;//OK
> >          // Don't copy this; it is per instance resultFileName =
> res.resultFileName;
> > @@ -617,6 +623,7 @@ public class SampleResult implements Ser
> >       *            the new responseData value
> >       */
> >      public void setResponseData(byte[] response) {
> > +        responseDataAsString = null;
> >          responseData = response == null ? EMPTY_BA : response;
> >      }
> >
> > @@ -631,6 +638,7 @@ public class SampleResult implements Ser
> >       */
> >      @Deprecated
> >      public void setResponseData(String response) {
> > +        responseDataAsString = null;
> >          try {
> >              responseData =
> response.getBytes(getDataEncodingWithDefault());
> >          } catch (UnsupportedEncodingException e) {
> > @@ -647,6 +655,7 @@ public class SampleResult implements Ser
> >       *
> >       */
> >      public void setResponseData(final String response, final String
> encoding) {
> > +        responseDataAsString = null;
> >          String encodeUsing = encoding != null? encoding :
> DEFAULT_CHARSET;
> >          try {
> >              responseData = response.getBytes(encodeUsing);
> > @@ -680,7 +689,10 @@ public class SampleResult implements Ser
> >       */
> >      public String getResponseDataAsString() {
> >          try {
> > -            return new
> String(responseData,getDataEncodingWithDefault());
> > +            if(responseDataAsString == null) {
> > +                responseDataAsString= new
> String(responseData,getDataEncodingWithDefault());
> > +            }
> > +            return responseDataAsString;
> >          } catch (UnsupportedEncodingException e) {
> >              log.warn("Using platform default as
> "+getDataEncodingWithDefault()+" caused "+e);
> >              return new String(responseData); // N.B. default charset is
> used deliberately here
> > @@ -1322,4 +1334,11 @@ public class SampleResult implements Ser
> >      public void setStartNextThreadLoop(boolean startNextThreadLoop) {
> >          this.startNextThreadLoop = startNextThreadLoop;
> >      }
> > +
> > +    /**
> > +     * Clean up cached data
> > +     */
> > +    public void cleanAfterSample() {
> > +        this.responseDataAsString = null;
> > +    }
> >  }
> >
> > Modified:
> jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
> > URL:
> http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java?rev=1418783&r1=1418782&r2=1418783&view=diff
> >
> ==============================================================================
> > --- jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
> (original)
> > +++ jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
> Sat Dec  8 23:23:03 2012
> > @@ -205,4 +205,13 @@ public class JMeterContext {
> >      public boolean isRestartNextLoop() {
> >          return restartNextLoop;
> >      }
> > +
> > +    /**
> > +     * Clean cached data after sample
> > +     */
> > +    public void cleanAfterSample() {
> > +        if(previousResult != null) {
> > +            previousResult.cleanAfterSample();
> > +        }
> > +    }
> >  }
> >
> > Modified:
> jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
> > URL:
> http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java?rev=1418783&r1=1418782&r2=1418783&view=diff
> >
> ==============================================================================
> > --- jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
> (original)
> > +++ jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
> Sat Dec  8 23:23:03 2012
> > @@ -254,6 +254,7 @@ public class JMeterThread implements Run
> >                  Sampler sam = controller.next();
> >                  while (running && sam != null) {
> >                         process_sampler(sam, null, threadContext);
> > +                       threadContext.cleanAfterSample();
> >                         if(onErrorStartNextLoop ||
> threadContext.isRestartNextLoop()) {
> >                             if(threadContext.isRestartNextLoop()) {
> >                              triggerEndOfLoopOnParentControllers(sam,
> threadContext);
> >
> >
>



-- 
Cordialement.
Philippe Mouawad.

Re: svn commit: r1418783 - in /jmeter/trunk/src/core/org/apache/jmeter: samplers/SampleResult.java threads/JMeterContext.java threads/JMeterThread.java

Posted by sebb <se...@gmail.com>.
On 8 December 2012 23:23,  <pm...@apache.org> wrote:
> Author: pmouawad
> Date: Sat Dec  8 23:23:03 2012
> New Revision: 1418783
>
> URL: http://svn.apache.org/viewvc?rev=1418783&view=rev
> Log:
> Bug 54268 - Improve memory and CPU usage
> Improve CPU by caching response as String instead of computing it for each post processor
> Improve memory by eagerly cleaning the cached field
> Bugzilla Id: 54268
>
> Modified:
>     jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
>     jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
>     jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
>
> Modified: jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java
> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java?rev=1418783&r1=1418782&r2=1418783&view=diff
> ==============================================================================
> --- jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java (original)
> +++ jmeter/trunk/src/core/org/apache/jmeter/samplers/SampleResult.java Sat Dec  8 23:23:03 2012
> @@ -245,6 +245,11 @@ public class SampleResult implements Ser
>
>      final long nanoThreadSleep;
>
> +    /**
> +     * Cache for responseData as string to avoid multiple computations
> +     */
> +    private String responseDataAsString;
> +

Should probably be transient.

Does it also need to be volatile? i.e. is it access from multiple threads?

>      private long initOffset(){
>          if (useNanoTime){
>              return nanoThreadSleep > 0 ? NanoOffset.getNanoOffset() : System.currentTimeMillis() - sampleNsClockInMs();
> @@ -298,6 +303,7 @@ public class SampleResult implements Ser
>          requestHeaders = res.requestHeaders;//OK
>          responseCode = res.responseCode;//OK
>          responseData = res.responseData;//OK
> +        responseDataAsString = null;
>          responseHeaders = res.responseHeaders;//OK
>          responseMessage = res.responseMessage;//OK
>          // Don't copy this; it is per instance resultFileName = res.resultFileName;
> @@ -617,6 +623,7 @@ public class SampleResult implements Ser
>       *            the new responseData value
>       */
>      public void setResponseData(byte[] response) {
> +        responseDataAsString = null;
>          responseData = response == null ? EMPTY_BA : response;
>      }
>
> @@ -631,6 +638,7 @@ public class SampleResult implements Ser
>       */
>      @Deprecated
>      public void setResponseData(String response) {
> +        responseDataAsString = null;
>          try {
>              responseData = response.getBytes(getDataEncodingWithDefault());
>          } catch (UnsupportedEncodingException e) {
> @@ -647,6 +655,7 @@ public class SampleResult implements Ser
>       *
>       */
>      public void setResponseData(final String response, final String encoding) {
> +        responseDataAsString = null;
>          String encodeUsing = encoding != null? encoding : DEFAULT_CHARSET;
>          try {
>              responseData = response.getBytes(encodeUsing);
> @@ -680,7 +689,10 @@ public class SampleResult implements Ser
>       */
>      public String getResponseDataAsString() {
>          try {
> -            return new String(responseData,getDataEncodingWithDefault());
> +            if(responseDataAsString == null) {
> +                responseDataAsString= new String(responseData,getDataEncodingWithDefault());
> +            }
> +            return responseDataAsString;
>          } catch (UnsupportedEncodingException e) {
>              log.warn("Using platform default as "+getDataEncodingWithDefault()+" caused "+e);
>              return new String(responseData); // N.B. default charset is used deliberately here
> @@ -1322,4 +1334,11 @@ public class SampleResult implements Ser
>      public void setStartNextThreadLoop(boolean startNextThreadLoop) {
>          this.startNextThreadLoop = startNextThreadLoop;
>      }
> +
> +    /**
> +     * Clean up cached data
> +     */
> +    public void cleanAfterSample() {
> +        this.responseDataAsString = null;
> +    }
>  }
>
> Modified: jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java
> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java?rev=1418783&r1=1418782&r2=1418783&view=diff
> ==============================================================================
> --- jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java (original)
> +++ jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterContext.java Sat Dec  8 23:23:03 2012
> @@ -205,4 +205,13 @@ public class JMeterContext {
>      public boolean isRestartNextLoop() {
>          return restartNextLoop;
>      }
> +
> +    /**
> +     * Clean cached data after sample
> +     */
> +    public void cleanAfterSample() {
> +        if(previousResult != null) {
> +            previousResult.cleanAfterSample();
> +        }
> +    }
>  }
>
> Modified: jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java
> URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java?rev=1418783&r1=1418782&r2=1418783&view=diff
> ==============================================================================
> --- jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java (original)
> +++ jmeter/trunk/src/core/org/apache/jmeter/threads/JMeterThread.java Sat Dec  8 23:23:03 2012
> @@ -254,6 +254,7 @@ public class JMeterThread implements Run
>                  Sampler sam = controller.next();
>                  while (running && sam != null) {
>                         process_sampler(sam, null, threadContext);
> +                       threadContext.cleanAfterSample();
>                         if(onErrorStartNextLoop || threadContext.isRestartNextLoop()) {
>                             if(threadContext.isRestartNextLoop()) {
>                              triggerEndOfLoopOnParentControllers(sam, threadContext);
>
>