JMeter测试结果时间解析
****************************************************************
作者:Fan Feng
本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议授权
****************************************************************

JMeter tips中写道:

In the context of Web applications, response time refers to the time elapsed between the submission of a request and the receipt of the resulting HTML. Technically, response time should include time for the browser to render the HTML page, but a browser typically displays the page piece by piece, making the perceived response time less. In addition, typically, a load-test tool calculates the response time without considering rendering time. Therefore, for practical purposes of performance testing, we adopt the definition described above. If in doubt, add a constant to the measured response time, say 0.5 seconds.

 

为了从Apache JMeter浩繁的Java源码中找出相关函数,幸好有Search and Replace for Windows(下载)能查找文件内容。

 

sampleEnd存在于文件:

jakarta-jmeter-2.3.3\src\components\org\apache\jmeter\sampler\DebugSampler.java

jakarta-jmeter-2.3.3\src\core\org\apache\jmeter\control\TransactionController.java

jakarta-jmeter-2.3.3\src\core\org\apache\jmeter\samplers\SampleResult.java

jakarta-jmeter-2.3.3\src\examples\org\apache\jmeter\examples\sampler\ExampleSampler.java

jakarta-jmeter-2.3.3\src\examples\org\apache\jmeter\examples\testbeans\example1\Example1.java

jakarta-jmeter-2.3.3\src\examples\org\apache\jmeter\examples\testbeans\example2\Example2.java

jakarta-jmeter-2.3.3\src\junit\org\apache\jmeter\protocol\java\sampler\JUnitSampler.java

jakarta-jmeter-2.3.3\src\protocol\ftp\org\apache\jmeter\protocol\ftp\sampler\FTPSampler.java

jakarta-jmeter-2.3.3\src\protocol\http\org\apache\jmeter\protocol\http\sampler\AjpSampler.java

jakarta-jmeter-2.3.3\src\protocol\http\org\apache\jmeter\protocol\http\sampler\HTTPSampler.java

jakarta-jmeter-2.3.3\src\protocol\http\org\apache\jmeter\protocol\http\sampler\HTTPSampler2.java

jakarta-jmeter-2.3.3\src\protocol\http\org\apache\jmeter\protocol\http\sampler\HTTPSamplerBase.java

jakarta-jmeter-2.3.3\src\protocol\http\org\apache\jmeter\protocol\http\sampler\SoapSampler.java

jakarta-jmeter-2.3.3\src\protocol\http\org\apache\jmeter\protocol\http\sampler\WebServiceSampler.java

jakarta-jmeter-2.3.3\src\protocol\java\org\apache\jmeter\protocol\java\sampler\BeanShellSampler.java

jakarta-jmeter-2.3.3\src\protocol\java\org\apache\jmeter\protocol\java\sampler\BSFSampler.java

jakarta-jmeter-2.3.3\src\protocol\java\org\apache\jmeter\protocol\java\sampler\JavaSamplerClient.java

jakarta-jmeter-2.3.3\src\protocol\java\org\apache\jmeter\protocol\java\test\JavaTest.java

jakarta-jmeter-2.3.3\src\protocol\java\org\apache\jmeter\protocol\java\test\SleepTest.java

jakarta-jmeter-2.3.3\src\protocol\jdbc\org\apache\jmeter\protocol\jdbc\sampler\JDBCSampler.java

jakarta-jmeter-2.3.3\src\protocol\jms\org\apache\jmeter\protocol\jms\sampler\JMSSampler.java

jakarta-jmeter-2.3.3\src\protocol\jms\org\apache\jmeter\protocol\jms\sampler\PublisherSampler.java

jakarta-jmeter-2.3.3\src\protocol\jms\org\apache\jmeter\protocol\jms\sampler\SubscriberSampler.java

jakarta-jmeter-2.3.3\src\protocol\ldap\org\apache\jmeter\protocol\ldap\sampler\LDAPExtSampler.java

jakarta-jmeter-2.3.3\src\protocol\ldap\org\apache\jmeter\protocol\ldap\sampler\LDAPSampler.java

jakarta-jmeter-2.3.3\src\protocol\mail\org\apache\jmeter\protocol\mail\sampler\MailReaderSampler.java

jakarta-jmeter-2.3.3\src\protocol\tcp\org\apache\jmeter\protocol\tcp\sampler\TCPSampler.java

jakarta-jmeter-2.3.3\test\src\org\apache\jmeter\samplers\TestSampleResult.java

中,定义在文件SampleResult.java中:

/**

     * Record the start time of a sample

     *

     */

    public void sampleStart() {

        if (startTime == 0) {

            setStartTime(currentTimeInMs());

        } else {

            log.error("sampleStart called twice", new Throwable("Invalid call sequence"));

        }

    }

 

    /**

     * Record the end time of a sample and calculate the elapsed time

     *

     */

    public void sampleEnd() {

        if (endTime == 0) {

            setEndTime(currentTimeInMs());

        } else {

            log.error("sampleEnd called twice", new Throwable("Invalid call sequence"));

        }

    }

 

HTTPSampler.java为例:

public class HTTPSampler extends HTTPSamplerBase implements Interruptible

………………………………………………………………………………….

protected HTTPSampleResult sample(URL url, String method, boolean areFollowingRedirect, int frameDepth) {

………………………………………………………………………………….

            // Request sent. Now get the response:

            byte[] responseData = readResponse(conn, res);

 

            res.sampleEnd();

            // Done with the sampling proper.

 

            // Now collect the results into the HTTPSampleResult:

            res.setResponseData(responseData);

…………………………………………………………………………………..

            res = resultProcessing(areFollowingRedirect, frameDepth, res);

 

            log.debug("End : sample");

            return res;

        } catch (IOException e) {

            res.sampleEnd();

…………………………………………………………………………………..

}

 

    /**

     * Reads the response from the URL connection.

     *

     * @param conn

     *            URL from which to read response

     * @return response content

     * @exception IOException

     *                if an I/O exception occurs

     */

    protected byte[] readResponse(HttpURLConnection conn, SampleResult res) throws IOException

 

文件HTTPSamplerBase.java中:

    /**

     * Follow redirects and download page resources if appropriate. this works,

     * but the container stuff here is what's doing it. followRedirects() is

     * actually doing the work to make sure we have only one container to make

     * this work more naturally, I think this method - sample() - needs to take

     * an HTTPSamplerResult container parameter instead of a

     * boolean:areFollowingRedirect.

     *

     * @param areFollowingRedirect

     * @param frameDepth

     * @param res

     * @return the sample result

     */

protected HTTPSampleResult resultProcessing(boolean areFollowingRedirect, int frameDepth, HTTPSampleResult res)

 

    /**

     * Read response from the input stream, converting to MD5 digest if the useMD5 property is set.

     *

     * For the MD5 case, the result byte count is set to the size of the original response.

     *

     * @param sampleResult

     * @param in input stream

     * @param length expected input length or zero

     * @return the response or the MD5 of the response

     * @throws IOException

     */

    public byte[] readResponse(SampleResult sampleResult, InputStream in, int length) throws IOException {

 

        byte[] readBuffer = getThreadContext().getReadBuffer();

        int bufferSize=32;// Enough for MD5

…………………………………………………………………………………..

        boolean first = true;

        while ((bytesRead = in.read(readBuffer)) > -1) {

            if (first) {

                sampleResult.latencyEnd();

                first = false;

            }

            if (asMD5 && md != null) {

                md.update(readBuffer, 0 , bytesRead);

                totalBytes += bytesRead;

            } else {

                w.write(readBuffer, 0, bytesRead);

            }

        }

        if (first){ // Bug 46838 - if there was no data, still need to set latency

            sampleResult.latencyEnd();

        }

        in.close();

…………………………………………………………………………………..

 

值得注意的是,虽然JMeter支持了CookiesUser-AgentHidden fieldsURL rewriting,但JMeter仍然没能完全模拟任何一款浏览器。