一般而言JMeter下性能最好的是jar包这类java原生请求,对于JMeter并没有原生支持的请求,一般都会将其直接编译为jar包,然后再JMeter中调用,这样性能最好。

但是有些需求并不适合用jar包的方式来进行,比如报文拼接,这个一般在请求Sampler发送前执行,比较方便的是使用BeanShell或者Groovy等前置处理器操作。那对于这种报文拼接的操作,使用JSR233组件还是BeanShell组件,以及使用JSR233组件中的BeanShell还是Groovy之间有没有什么性能差异呢?

我们去翻了翻JMeter官方的相关介绍,只在JMeter官网的最佳实践“http://jmeter.apache.org/usermanual/best-practices.html”中找到对JSR233组件有如下的描述:

强烈建议在大压力测试场景中使用Groovy这个可以预编译的语言,而BeanShell虽然也实现了预编译的接口,但是却没有被编码进去。这段介绍并没有说JSR233组件和BeanShell组件之间的性能差异。

下面我们就写三个简单的脚本来看一下在前置处理器中Groovy和BeanShell两种语言以及JSR233组件和BeanShell组件的性能差异。脚本截图如下,文章最下面放上jxm原文件。

Groovy和BeanShell的前置处理器中的代码非常简单,就是vars.put生成一个JMeter参数

每个脚本,我们设置为300VU,500TPS,执行5分钟,采用CLI方式执行,执行完后,切割中间的3分钟生成报告,服务器的硬件为8核CPUE7-4820。具体执行结果如下:

从试验结果可以得出如下几个很明显的现象:

  • JSR233组件下的BeanShell性能非常差。

  • 同一个场景中,如果有的脚本使用了JSR233组件下的BeanShell语言,那会严重影响当前场景下的所有BeanShell组件模块的性能;同时也会稍微影响JSR233组件下的Groovy语言的性能,导致其TPS略有下降。

  • BeanShell组件下的BeanShell语言性能比JSR233组件下的Groovy语言性能稍差,实测TPS基本一致。

通过本次试验,在此提醒大家,在编写JMeter脚本的时候,千万不要使用JSR233组件下的BeanShell语言,如果要使用BeanShell语言一定要用BeanShell组件下的。

喜欢请长按下方二维码关注我的个人微信号,测试杂货铺。^_^

Groovy和BeanShell性能比较.JMX的源文件如下,复制然后保存成jmx就可以在JMeter中使用:

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.1 r1853635">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group Groovy" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">300</stringProp>
<stringProp name="ThreadGroup.ramp_time">10</stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">300</stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<kg.apc.jmeter.samplers.DummySampler guiclass="kg.apc.jmeter.samplers.DummySamplerGui" testclass="kg.apc.jmeter.samplers.DummySampler" testname="DummyGroovy" enabled="true">
<boolProp name="WAITING">true</boolProp>
<boolProp name="SUCCESFULL">true</boolProp>
<stringProp name="RESPONSE_CODE">200</stringProp>
<stringProp name="RESPONSE_MESSAGE">OK</stringProp>
<stringProp name="REQUEST_DATA">${testvars1}</stringProp>
<stringProp name="RESPONSE_DATA">Dummy Sampler used to simulate requests and responses
without actual network activity. This helps debugging tests.</stringProp>
<stringProp name="RESPONSE_TIME">${__Random(50,500)}</stringProp>
<stringProp name="LATENCY">${__Random(1,50)}</stringProp>
<stringProp name="CONNECT">${__Random(1,5)}</stringProp>
</kg.apc.jmeter.samplers.DummySampler>
<hashTree>
<JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="JSR223 PreProcessor" enabled="true">
<stringProp name="cacheKey">true</stringProp>
<stringProp name="filename"></stringProp>
<stringProp name="parameters"></stringProp>
<stringProp name="script">vars.put("testvars1","testvars1Groovy")</stringProp>
<stringProp name="scriptLanguage">groovy</stringProp>
</JSR223PreProcessor>
<hashTree/>
</hashTree>
<ConstantThroughputTimer guiclass="TestBeanGUI" testclass="ConstantThroughputTimer" testname="Constant Throughput Timer" enabled="true">
<intProp name="calcMode">2</intProp>
<doubleProp>
<name>throughput</name>
<value>30000.0</value>
<savedValue>0.0</savedValue>
</doubleProp>
</ConstantThroughputTimer>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group JSR233BeanShell" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">300</stringProp>
<stringProp name="ThreadGroup.ramp_time">10</stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">300</stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<kg.apc.jmeter.samplers.DummySampler guiclass="kg.apc.jmeter.samplers.DummySamplerGui" testclass="kg.apc.jmeter.samplers.DummySampler" testname="DummyJSR233BeanShell" enabled="true">
<boolProp name="WAITING">true</boolProp>
<boolProp name="SUCCESFULL">true</boolProp>
<stringProp name="RESPONSE_CODE">200</stringProp>
<stringProp name="RESPONSE_MESSAGE">OK</stringProp>
<stringProp name="REQUEST_DATA">${testvars1}</stringProp>
<stringProp name="RESPONSE_DATA">Dummy Sampler used to simulate requests and responses
without actual network activity. This helps debugging tests.</stringProp>
<stringProp name="RESPONSE_TIME">${__Random(50,500)}</stringProp>
<stringProp name="LATENCY">${__Random(1,50)}</stringProp>
<stringProp name="CONNECT">${__Random(1,5)}</stringProp>
</kg.apc.jmeter.samplers.DummySampler>
<hashTree>
<JSR223PreProcessor guiclass="TestBeanGUI" testclass="JSR223PreProcessor" testname="JSR223 PreProcessor" enabled="true">
<stringProp name="scriptLanguage">beanshell</stringProp>
<stringProp name="parameters"></stringProp>
<stringProp name="filename"></stringProp>
<stringProp name="cacheKey">true</stringProp>
<stringProp name="script">vars.put("testvars1","testvars1BeanShell");</stringProp>
</JSR223PreProcessor>
<hashTree/>
</hashTree>
<ConstantThroughputTimer guiclass="TestBeanGUI" testclass="ConstantThroughputTimer" testname="Constant Throughput Timer" enabled="true">
<intProp name="calcMode">2</intProp>
<doubleProp>
<name>throughput</name>
<value>30000.0</value>
<savedValue>0.0</savedValue>
</doubleProp>
</ConstantThroughputTimer>
<hashTree/>
</hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group BeanShellBeanShell" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">300</stringProp>
<stringProp name="ThreadGroup.ramp_time">10</stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">300</stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<kg.apc.jmeter.samplers.DummySampler guiclass="kg.apc.jmeter.samplers.DummySamplerGui" testclass="kg.apc.jmeter.samplers.DummySampler" testname="DummyBeanShell" enabled="true">
<boolProp name="WAITING">true</boolProp>
<boolProp name="SUCCESFULL">true</boolProp>
<stringProp name="RESPONSE_CODE">200</stringProp>
<stringProp name="RESPONSE_MESSAGE">OK</stringProp>
<stringProp name="REQUEST_DATA">${testvars1}</stringProp>
<stringProp name="RESPONSE_DATA">Dummy Sampler used to simulate requests and responses
without actual network activity. This helps debugging tests.</stringProp>
<stringProp name="RESPONSE_TIME">${__Random(50,500)}</stringProp>
<stringProp name="LATENCY">${__Random(1,50)}</stringProp>
<stringProp name="CONNECT">${__Random(1,5)}</stringProp>
</kg.apc.jmeter.samplers.DummySampler>
<hashTree>
<BeanShellPreProcessor guiclass="TestBeanGUI" testclass="BeanShellPreProcessor" testname="BeanShell PreProcessor" enabled="true">
<stringProp name="filename"></stringProp>
<stringProp name="parameters"></stringProp>
<boolProp name="resetInterpreter">false</boolProp>
<stringProp name="script">vars.put("testvars1","testvars1BeanShell");</stringProp>
</BeanShellPreProcessor>
<hashTree/>
</hashTree>
<ConstantThroughputTimer guiclass="TestBeanGUI" testclass="ConstantThroughputTimer" testname="Constant Throughput Timer" enabled="true">
<intProp name="calcMode">2</intProp>
<doubleProp>
<name>throughput</name>
<value>30000.0</value>
<savedValue>0.0</savedValue>
</doubleProp>
</ConstantThroughputTimer>
<hashTree/>
</hashTree>
<ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="false">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>false</xml>
<fieldNames>true</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
<sentBytes>true</sentBytes>
<url>true</url>
<threadCounts>true</threadCounts>
<idleTime>true</idleTime>
<connectTime>true</connectTime>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</jmeterTestPlan>

JMeter下Groovy和BeanShell语言在不同组件中性能差异实践探究的更多相关文章

  1. linux终端下 编译c语言程序

    linux终端下,编译C语言程序步骤为: 采用vi进行源代码编写,编写完成后,:wq存盘退出,如: vi test.c 在命令行下,运行gcc编译程序,生成执行码,如: gcc  -o test te ...

  2. Linux centos 7/ubantu下: 用 C 语言连接 MySQL数据库

    前言:最近用IPC.socket做ATM.聊天项目,考虑到需要用到数据库,所以总结一下centos.ubantu环境下怎么用C语言操作数据库,例如常见的增删改查等! 一.Centos环境安装mysql ...

  3. ubuntu下如何编译C语言

    ubuntu下如何编译C语言     如果没有gcc编译器的话,使用以下命令获取 ~# sudo apt-get install gcc同时要下载辅助工具 ~# sudo apt-get instal ...

  4. Ubuntu下在Eclipse IDE for C/C++ Developers中怎样执行C语言的GTK程序?(已解决)

    (已解决.详见Ubuntu 12.04下在Eclipse IDE for C/C++ Developers中执行C语言的GTK程序) 按"Ubuntu下GTK的安装.编译和測试"( ...

  5. linux环境下安装可操作图库语言Gremlin的图框架HugeGraph

    原创/朱季谦 图数据库是一项比较前沿而逐渐热门的技术,是NoSql数据库的一种,它应用图形理论存储实体之间的关系信息,最主要的组成有两种,结点集和连接结点的边.常见的图数据库有Neo4j,Januas ...

  6. Linux系统下C语言如何调用scalapack中的函数

    在并行计算中经常需要调用scalapck(并行化的lapack)函数库里面的函数进行编程,这里简单介绍在C语言如何调用scalapck中的矩阵向量乘的函数. 注意:scalapack中的函数是用for ...

  7. C++下混合编译c语言方法总结

    最近在读SGI STL源码,感觉对C++的学习很有帮助,之前对于泛型.iterator.traits等等各种特性的概念非常模糊,通过这两天的琢磨,再加上<STL 源码剖析>的帮助,对C++ ...

  8. 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解

    Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解   多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...

  9. Swift - 使用下划线(_)来分隔数值中的数字

    为了增强较大数值的可读性,Swift语言增加了下划线(_)来分隔数值中的数字. 不管是整数,还是浮点数,都可以使用下划线来分隔数字. 1 2 3 4 //数值可读性 let value1 = 10_0 ...

随机推荐

  1. October 03rd 2017 Week 40th Tuesday

    Don't make promises you can't keep. But those are the best kind. 不要许下做不到的承诺,但是我们做不到的承诺往往是最好的. The be ...

  2. Linux 下安装配置 JDK7 配置环境(debian 7)

    自从从Oracle收购Sun近三年来,已经有很多变化.早在8月,甲骨文将“Operating System Distributor License for Java”许可证终结,这意味着第三方将不可以 ...

  3. struts2中的文件上传和下载

    天下大事,必做于细.天下难事,必作于易. 以前见过某些人,基础的知识还不扎实就去学习更难的事,这样必定在学习新的知识会非常迷惑结果 再回来又一次学习一下没有搞懂的知识,这必定会导致学习效率的下降!我写 ...

  4. 【洛谷】【堆】P1168 中位数

    [题目描述:] 给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[3], …, A[2k - 1]的中位数.即前1,3,5,……个数的中位数. ...

  5. gcd?人生赢家!

    题目背景 原创:b2019dy gcd是一个热爱游戏的人 题目描述 gcd最近在玩一个有趣的游戏 我们把这个游戏抽象成一张图,图上有n个点,我们需要寻找总计m件宝物,它们分布在图上,对于每件宝物而言, ...

  6. 安卓预览报错 Failed to load AppCompat ActionBar with unknown error

    报错信息 : Render ProblemFailed to load AppCompat ActionBar with unknown error. Failed to instantiate on ...

  7. 对于高并发短连接造成Cannot assign requested address解决方法

    https://www.cnblogs.com/dadonggg/p/8778318.html 感谢这篇文章给予的启发 在tcp四次挥手断开连接时,主动释放连接的一方最后会进入TIME_WAIT状态, ...

  8. Day2 CSS

    什么是CSS 层叠样式表(cascading style sheet) 控制页面元素的显示方式.(添加样式) CSS语法 行间样式 行内式是在标记的style属性中设定CSS样式.这种方式没有体现出C ...

  9. virtualbox+vagrant学习-2(command cli)-25-Machine Readable Output

    Machine Readable Output机器可读的输出 每个vagrant命令都接受一个--machine-readable的标志,它支持机器可读的输出模式.在这种模式下,终端的输出被机器友好的 ...

  10. opencv——Rect和RotatedRect类详解

    https://blog.csdn.net/u012819339/article/details/82217667  //不好 https://blog.csdn.net/mailzst1/artic ...