在编写任何JMeter组件时,必须注意某些特定的约定——如果JMeter环境中正确地运行JMeter组件,那么它将会运行。本部分描述了组件的GUI部分必须满足的约定。

JMeter中的GUI代码严格地与测试元件代码(这里指逻辑控制代码,下同)分离。因此,当编写一个组件时,将会有一个用于测试元件的类,另一个用于GUI表示。GUI类是无状态的,因此它不应该挂在对测试元件的引用上(尽管有例外)。

GUI元素应该继承适当的抽象类:

  • AbstractSamplerGui
  • AbstractAssertionGui
  • AbstractConfigGui
  • AbstractControllerGui
  • AbstractPostProcessorGui
  • AbstractPreProcessorGui
  • AbstractVisualizer
  • AbstractTimerGui
  • ……

这些抽象类提供了大量的管道工作,不用扩展,用来代替直接实现接口。

已经继承了适当的GUI类,剩下要遵循以下步骤:

1、实现getResourceLabel() 
该方法返回资源的标题/名称。 
2、创建GUI。无论使用什么样式,都要布局GUI。类最终要继承JPanel,因此布局必须在的类自己的ContentPane中。不要通过动作和事件将·GUI元素连接到测试元件类。让swing的内部模型尽可能多地挂在所有数据上。 
(1)一些标准的GUI内容应该添加到所有JMeter GUI组件中: 
a、调用setBorder(makeBorder())。这将给它提供标准的JMeter边框。 
b、通过makeTitlePanel()添加标题窗格。通常这是添加到GUI中的第一件事,应该在一个垂直布局方案中完成,或者使用JMeter的VerticalLayout类。下面是一个示例init()方法:

private void init() {
setLayout(new BorderLayout());
setBorder(makeBorder());
Box box = Box.createVerticalBox();
box.add(makeTitlePanel());
box.add(makeSourcePanel());
add(box,BorderLayout.NORTH);
add(makeParameterPanel(),BorderLayout.CENTER);
}

3、实现public void configure(TestElement el) 
(1)一定调用super.configure(e),这将填充一些数据,比如元素的名称 
(2)使用此方法将数据设置为GUI元素。例子

public void configure(TestElement el) {
super.configure(el);
useHeaders.setSelected(el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
useBody.setSelected(!el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
regexField.setText(el.getPropertyAsString(RegexExtractor.REGEX));
templateField.setText(el.getPropertyAsString(RegexExtractor.TEMPLATE));
defaultField.setText(el.getPropertyAsString(RegexExtractor.DEFAULT));
matchNumberField.setText(el.getPropertyAsString(RegexExtractor.MATCH_NUM));
refNameField.setText(el.getPropertyAsString(RegexExtractor.REFNAME));
}

(3)实现public void modifyTestElement(TestElement e),这是将数据从GUI元素移动到TestElement的地方。这是前一种方法的逻辑逆操作 
a、调用super.configureTestElement(e),处理一些默认数据 
b、例子

public void modifyTestElement(TestElement e) {
super.configureTestElement(e);
e.setProperty(new BooleanProperty(
RegexExtractor.USEHEADERS,
useHeaders.isSelected()));
e.setProperty(RegexExtractor.MATCH_NUMBER,
matchNumberField.getText());
if (e instanceof RegexExtractor) {
RegexExtractor regex = (RegexExtractor)e;
regex.setRefName(refNameField.getText());
regex.setRegex(regexField.getText());
regex.setTemplate(templateField.getText());
regex.setDefaultValue(defaultField.getText());
}
}

(4)实现public TestElement createTestElement(),该方法应该创建TestElement类的一个新实例,然后将其传递modifyTestElement(TestElement)方法

public TestElement createTestElement() {
RegexExtractor extractor = new RegexExtractor();
modifyTestElement(extractor);
return extractor;
}

不能保留对测试元件的引用的原因是因为JMeter的测试元件重用了多个GUI类对象的实例。这样可以节省很多内存。它还使得编写新组件的GUI部分变得非常容易。您仍然需要与Swing中的布局进行斗争,但是不必担心如何创建正确的事件和从GUI元素中获取数据放入测试元件中。JMeter知道什么时候调用自定义配置,以及可以用一种非常简单的方式来完成它的修改。

总结:

GUI与测试元件分离:GUI部分通过继承各种组件GUI抽象类,测试元件部分通过继承组件抽象类和实现各种接口方式从而实现不同组件的内部逻辑控制;
GUI与测试元件不分离:与分离方法的区别在于不单独实现GUI部分,在测试元件部分通过实现TestBean接口方法从而实现对GUI界面的配置。(TestBean是一个空接口:Marker interface to tell JMeter to make a Test Bean Gui for the class)

jmeter插件分类

GUI的组件主要包括10大组件

  • ThreadGroup(线程组)
  • Test Fragment(测试片段)
  • logic Controller(逻辑控制器)
  • Config element(配置元件)
  • Timer(定时器)
  • pre processor(前置处理器)
  • post processor(后置处理器)
  • Sampler(测试抽样器)
  • Assertion(断言)
  • Listener(监听器);

非GUI组件

  • Function(函数)

JMeter插件式组件实现

TestElement是所有组件的最基本单元,组件类都是TestElement类的子类 
依据上面介绍,组件的实现分两部分:GUI和TestElement

GUI部分的实现

继承实现对应的抽象类

抽象类 继承的类 对应组件备注
AbstractAssertionGui AbstractScopedJMeterGuiComponent 断言
AbstractConfigGui AbstractJMeterGuiComponent 配置
AbstractControllerGui AbstractJMeterGuiComponent 控制
AbstractPostProcessorGui AbstractScopedJMeterGuiComponent 后置处理器
AbstractPreProcessorGui AbstractJMeterGuiComponent 前置处理器
AbstractSamplerGui AbstractJMeterGuiComponent 取样器
AbstractThreadGroupGui AbstractJMeterGuiComponent 线程组
AbstractTimerGui AbstractJMeterGuiComponent 定时器
AbstractListenerGui AbstractJMeterGuiComponent 监听器
AbstractVisualizer AbstractListenerGui 组件依赖
AbstractScopedJMeterGuiComponent AbstractJMeterGuiComponent 组件依赖
AbstractJMeterGuiComponent JPanel 组件依赖
AbstractFunction Function 组件依赖
AbstractJMeterGuiComponent JPanel 组件依赖

逻辑控制实现

Assertion(断言)组件

Assertion(断言)组件通过继承AbstractTestElement抽象类(或者AbstractTestElement子类),实现Assertion接口的getResult(SampleResult result)方法对结果内容进行判断,从而实现断言方法,用于对Sampler组件所产生的抽样采集结果内容进行断言。

比如:

public class XMLSchemaAssertion extends AbstractTestElement implements Serializable, Assertion {
……
@Override
public AssertionResult getResult(SampleResult response) {
AssertionResult result = new AssertionResult(getName());
……
return result;
}
……
}

再比如:

public abstract class AbstractScopedTestElement extends AbstractTestElement {...}
public abstract class AbstractScopedAssertion extends AbstractScopedTestElement{...} public class DurationAssertion extends AbstractScopedAssertion implements Serializable, Assertion {
public static final String DURATION_KEY = "DurationAssertion.duration";
@Override
public AssertionResult getResult(SampleResult response) {
……
return result;
}
private long getAllowedDuration() {
return getPropertyAsLong(DURATION_KEY);
}
public void setAllowedDuration(long duration) {
setProperty(DURATION_KEY, duration);
}
}

Config(配置元件)组件

Config(配置元件)组件相对其他组件比较特殊,通过继承ConfigTestElement类或只需要GUI部分的实现即可完成本体任务

public class CSVDataSet extends ConfigTestElement
implements TestBean, LoopIterationListener, NoConfigMerge {
private static final Logger log = LoggerFactory.getLogger(CSVDataSet.class);
……
}

ThreadGroup(线程组)组件

ThreadGroup(线程组)组件继承AbstractThreadGroup抽象类,通过重写各类控制方法来达到控制和协调各线程(虚拟用户)的行为,线程组是构建一个性能测试模型的最基本组件。

public class ThreadGroupTest extends AbstractThreadGroup {
private static final long serialVersionUID = 1L;
@Override
public void threadFinished(JMeterThread arg0) {}
@Override
public int numberOfActiveThreads() {return 0;}
@Override
public void start(int arg0, ListenerNotifier arg1, ListedHashTree arg2, StandardJMeterEngine arg3) {}
@Override
public void stop() {}
@Override
public boolean stopThread(String arg0, boolean arg1) {return false;}
@Override
public void tellThreadsToStop() {}
@Override
public boolean verifyThreadsStopped() {return false;}
@Override
public void waitThreadsStopped() {}
}

Timer(定时器)组件

Timer(定时器)组件通过继承AbstractTestElement抽象类,实现Timer接口的delay()方法来实现对时间的控制

public class TimerTest extends AbstractTestElement implements Timer{
private static final long serialVersionUID = 1L;
@Override
public long delay() {
return 0;
}
}

控制线程延时,即用来模仿思考时间(ThinkTime)或键盘时间(KeyTime);

控制线程行为,如SyncTimer(同步计时器),就是内部利用CyclicBarrier来控制阻塞和释放全部运行线程的逻辑行为,从而达到“集合点”的目的。

public class SyncTimer extends AbstractTestElement implements Timer, Serializable, TestBean, TestStateListener, ThreadListener {
private static final Logger log = LoggerFactory.getLogger(SyncTimer.class);
private static class BarrierWrapper implements Cloneable {
private CyclicBarrier barrier;
public BarrierWrapper() {
this.barrier = null;
}
public BarrierWrapper(int parties) {
this.barrier = new CyclicBarrier(parties);
}
public synchronized void setup(int parties) {
if(this.barrier== null) {
this.barrier = new CyclicBarrier(parties);
}
}
public int await() throws InterruptedException, BrokenBarrierException{
return barrier.await();
}
public int await(long timeout, TimeUnit timeUnit) throws InterruptedException, BrokenBarrierException, TimeoutException {
return barrier.await(timeout, timeUnit);
}
public void reset() {
barrier.reset();
}
@Override
protected Object clone() {
BarrierWrapper barrierWrapper= null;
try {
barrierWrapper = (BarrierWrapper) super.clone();
barrierWrapper.barrier = this.barrier;
} catch (CloneNotSupportedException e) {
}
return barrierWrapper;
}
}
……
public void threadStarted() {
if(getGroupSize() == 0) {
int numThreadsInGroup = JMeterContextService.getContext().getThreadGroup().getNumThreads();
// Unique Barrier creation ensured by synchronized setup
this.barrier.setup(numThreadsInGroup);
}
}
……
}

pre processor(前置处理器)组件

pre processor(前置处理器)组件通过继承AbstractTestElement抽象类,实现PreProcessor接口的process ()方法控制逻辑

比如:BeanShellPreProcessor

public class BeanShellPreProcessor extends BeanShellTestElement
implements Cloneable, PreProcessor, TestBean
{
private static final Logger log = LoggerFactory.getLogger(BeanShellPreProcessor.class); private static final long serialVersionUID = 5; // can be specified in jmeter.properties
private static final String INIT_FILE = "beanshell.preprocessor.init"; //$NON-NLS-1$ @Override
protected String getInitFileProperty() {
return INIT_FILE;
}
@Override
public void process(){
final BeanShellInterpreter bshInterpreter = getBeanShellInterpreter();
if (bshInterpreter == null) {
log.error("BeanShell not found");
return;
}
JMeterContext jmctx = JMeterContextService.getContext();
Sampler sam = jmctx.getCurrentSampler();
try {
// Add variables for access to context and variables
bshInterpreter.set("sampler", sam);//$NON-NLS-1$
processFileOrScript(bshInterpreter);
} catch (JMeterException e) {
if (log.isWarnEnabled()) {
log.warn("Problem in BeanShell script. {}", e.toString());
}
}
}
@Override
public Object clone() {
return super.clone();
}
}

作用:对线程上下文中的当前Sampler和前一个SampleResult进行识别和判断。

post processor(后置处理器)组件

post processor(后置处理器)组件通过继承AbstractTestElement抽象类,实现PostProcessor接口的process ()方法控制逻辑

public abstract class AbstractScopedTestElement extends AbstractTestElement {……}

public class RegexExtractor extends AbstractScopedTestElement implements PostProcessor, Serializable {
……
@Override
public void process() {}
……
}

作用:对线程上下文中的前一个SampleResult进行识别和判断。

Controller(控制器)组件

Controller(控制器)组件通过继承GenericController类 
比如foreach,重写isDone、next、nextIsNull、getIterCount、reInitialize、initialize、triggerEndOfLoop

public class ForeachController extends GenericController implements Serializable {
public ForeachController() {}
……
@Override
public boolean isDone() {}
@Override
public Sampler next() {}
@Override
protected Sampler nextIsNull() throws NextIsNullException {}
@Override
protected int getIterCount() {return loopCount+1;}
@Override
protected void reInitialize() {}
@Override
public void triggerEndOfLoop() {}
@Override
public void initialize() {}
}

Sampler(测试抽样器)组件

Sampler(测试抽样器)组件继承AbstractSampler抽象类,通过重写SampleResult sample(Entry e)方法,实现测试过程以及测试结果的采集功能。

public class DebugSampler extends AbstractSampler implements TestBean {
……
@Override
public SampleResult sample(Entry e) {}
……
}

Listener(监听器)

直接继承AbstractTestElement,实现sampleListener或Visualizer等接口方法

public class Summariser extends AbstractTestElement
implements Serializable, SampleListener, TestStateListener, NoThreadClone, Remoteable {
……
@Override
@SuppressWarnings("SynchronizeOnNonFinalField")
public void sampleOccurred(SampleEvent e) {
SampleResult s = e.getResult();
if(IGNORE_TC_GENERATED_SAMPLERESULT && TransactionController.isFromTransactionController(s)) {
return;
}
long now = System.currentTimeMillis() / 1000;// in seconds
SummariserRunningSample myDelta = null;
SummariserRunningSample myTotal = null;
boolean reportNow = false;
synchronized (myTotals) {
if (s != null) {
myTotals.delta.addSample(s);
}
if ((now > myTotals.last + INTERVAL_WINDOW) && (now % INTERVAL <= INTERVAL_WINDOW)) {
reportNow = true;
// copy the data to minimise the synch time
myDelta = new SummariserRunningSample(myTotals.delta);
myTotals.moveDelta();
myTotal = new SummariserRunningSample(myTotals.total);
myTotals.last = now; // stop double-reporting
}
}
if (reportNow) {
formatAndWriteToLog(myName, myDelta, "+");
// Only if we have updated them
if (myTotal != null && myDelta != null &&myTotal.getNumSamples() != myDelta.getNumSamples()) { // NOSONAR
formatAndWriteToLog(myName, myTotal, "=");
}
}
}
……
}

可以从实际用途上将其分为两大类Report (报告)和Visualizers(监视器)。 
Report (报告)继承AbstractListenerElement抽象类,通过实现sampleOccurred(SampleEvent e)方法,对所有采集事件中所产生的SampleResult进行处理,从而生成报告;

public class ResultCollector extends AbstractListenerElement implements SampleListener, Clearable, Serializable,
TestStateListener, Remoteable, NoThreadClone {
……
@Override
public void sampleOccurred(SampleEvent event) {
SampleResult result = event.getResult(); if (isSampleWanted(result.isSuccessful())) {
sendToVisualizer(result);
if (out != null && !isResultMarked(result) && !this.isStats) {
SampleSaveConfiguration config = getSaveConfig();
result.setSaveConfig(config);
try {
if (config.saveAsXml()) {
SaveService.saveSampleResult(event, out);
} else { // !saveAsXml
String savee = CSVSaveService.resultToDelimitedString(event);
out.println(savee);
}
} catch (Exception err) {
log.error("Error trying to record a sample", err); // should throw exception back to caller
}
}
}
if(summariser != null) {
summariser.sampleOccurred(event);
}
}
……
}

Visualizers(监视器)主要用于特定的监控任务,比如监控系统资源利用率的组件,与Report的区别在于Visualizers必须继承一个 ResultCollector类,并在收集器中通过开启额外线程方式完成自定义的数据采集。

public class ResultCollector extends AbstractListenerElement implements SampleListener, Clearable, Serializable, TestStateListener, Remoteable, NoThreadClone {……}

比如标准插件中自定义一个JMXMonCollector

public class CorrectedResultCollector extends ResultCollector {}

public class JMXMonCollector extends CorrectedResultCollector implements Runnable, JMXMonSampleGenerator {……}
注意:对于一个需要配置的组件类则需要实现ConfigMergabilityIndicator接口的public boolean applies(ConfigTestElement configElement)方法,用来指明哪些Config组件可以用来对其进行配置

这里参考DebugSampler的源代码如下:

public class DebugSampler extends AbstractSampler implements TestBean {
……
private static final Set<String> APPLIABLE_CONFIG_CLASSES = new HashSet<>(
Arrays.asList("org.apache.jmeter.config.gui.SimpleConfigGui"));
@Override
public boolean applies(ConfigTestElement configElement) {
String guiClass = configElement.getProperty(TestElement.GUI_CLASS).getStringValue();
return APPLIABLE_CONFIG_CLASSES.contains(guiClass);
}
……
}

以上代码指明SimpleConfigGui配置元件可以对DebugSampler组件进行配置。

函数

Function(函数)是非GUI组件,这类组件的实现比较简单,而且功能比较单一,只需要继承相应的抽象类即可~

写一个求字符长度的函数:StrLen

public class StrLen extends AbstractFunction {
private static final List<String> desc = new LinkedList<String>();
private static final String KEY = "__strLen";
static {
desc.add("String to measure length");
desc.add("Name of variable in which to store the result (optional)");
}
private Object[] values;
public StrLen() {
}
@Override
public synchronized String execute(SampleResult previousResult, Sampler currentSampler)
throws InvalidVariableException {
JMeterVariables vars = getVariables();
Integer len = ((CompoundVariable) values[0]).execute().length();
if (vars != null && values.length > 1) {
String varName = ((CompoundVariable) values[1]).execute().trim();
vars.put(varName, len.toString());
}
return len.toString();
}
@Override
public synchronized void setParameters(Collection<CompoundVariable> parameters) throws InvalidVariableException {
checkMinParameterCount(parameters, 1);
values = parameters.toArray();
}
@Override
public String getReferenceKey() {
return KEY;
}
public List<String> getArgumentDesc() {
return desc;
}
}

附录

jmeter一些GUI类继承关系

GUI类 继承的类
ResultActionGui AbstractPostProcessorGui
ResultSaverGui AbstractListenerGui
SummariserGui AbstractListenerGui
TestBeanGUI AbstractJMeterGuiComponent
ThreadGroupGui AbstractThreadGroupGui
SetupThreadGroupGui ThreadGroupGui
PostThreadGroupGui ThreadGroupGui
WorkBenchGui AbstractJMeterGuiComponent
AssertionGui AbstractAssertionGui
BeanShellAssertionGui AbstractAssertionGui
urationAssertionGui AbstractAssertionGui
HTMLAssertionGui AbstractAssertionGui
MD5HexAssertionGUI AbstractAssertionGui
SizeAssertionGui AbstractAssertionGui
SMIMEAssertionGui AbstractAssertionGui
XMLAssertionGui AbstractAssertionGui
XMLSchemaAssertionGUI AbstractAssertionGui
XPathAssertionGui AbstractAssertionGui
CriticalSectionControllerGui AbstractControllerGui
IncludeControllerGui AbstractControllerGui
InterleaveControlGui AbstractControllerGui
ModuleControllerGui AbstractControllerGui
OnceOnlyControllerGui AbstractControllerGui
RandomControlGui AbstractControllerGui
RandomOrderControllerGui LogicControllerGui
SwitchControllerGui AbstractControllerGui
ThroughputControllerGui AbstractControllerGui
HtmlExtractorGui AbstractPostProcessorGui
RegexExtractorGui AbstractPostProcessorGui
XPathExtractorGui AbstractPostProcessorGui
JSONPostProcessorGui AbstractPostProcessorGui
CounterConfigGui AbstractConfigGui
SampleTimeoutGui AbstractPreProcessorGui
UserParametersGui AbstractPreProcessorGui
TestActionGui AbstractSamplerGui
AbstractRandomTimerGui AbstractTimerGui
ConstantTimerGui AbstractTimerGui
GaussianRandomTimerGui AbstractRandomTimerGui
PoissonRandomTimerGui AbstractRandomTimerGui
UniformRandomTimerGui AbstractRandomTimerGui
AbstractAssertionGui AbstractScopedJMeterGuiComponent
AbstractConfigGui AbstractJMeterGuiComponent
LoginConfigGui AbstractConfigGui
ObsoleteGui AbstractJMeterGuiComponent
SimpleConfigGui AbstractConfigGui
AbstractControllerGui AbstractJMeterGuiComponent
LogicControllerGui AbstractControllerGui
RunTimeGui AbstractControllerGui
TestFragmentControllerGui AbstractControllerGui
TestPlanGui AbstractJMeterGuiComponent
TransactionControllerGui AbstractControllerGui
WhileControllerGui AbstractControllerGui
WorkBenchGui AbstractJMeterGuiComponent
FunctionHelper JDialog
AbstractJMeterGuiComponent JPanel
AbstractScopedJMeterGuiComponent AbstractJMeterGuiComponent
AbstractPostProcessorGui AbstractScopedJMeterGuiComponent
AbstractPreProcessorGui AbstractJMeterGuiComponent
ResultActionGui AbstractPostProcessorGui
ResultSaverGui AbstractListenerGui
SummariserGui AbstractListenerGui
AbstractSamplerGui AbstractJMeterGuiComponent
TestBeanGUI AbstractJMeterGuiComponent
AbstractThreadGroupGui AbstractJMeterGuiComponent
PostThreadGroupGui ThreadGroupGui
SetupThreadGroupGui ThreadGroupGui
ThreadGroupGui AbstractThreadGroupGui
AbstractTimerGui AbstractJMeterGuiComponent
AbstractListenerGui AbstractJMeterGuiComponent
AbstractVisualizer AbstractListenerGui

JMeter Gui – TestElement约定(转自约会言行的博客,链接:http://blog.csdn.net/yue530tomtom/article/details/77649872?locationNum=4&fps=1)的更多相关文章

  1. JMeter Gui – TestElement约定[转]

    转自https://www.cnblogs.com/yigui/p/7615635.html 在编写任何JMeter组件时,必须注意某些特定的约定--如果JMeter环境中正确地运行JMeter组件, ...

  2. 笔记1:jmeter性能测试使用示例(原文:http://blog.csdn.net/zhongweijian/article/details/7619319)

    jmeter是一个简单开源的纯java的性能测试工具.今天学习了jmeter使用了下jmeter,使用起来非常简单. 如果我们要对163的首页性能进行简单测试,我们可以按照以下步骤进行. 1.在测试计 ...

  3. 24. Jmeter GUI 及NON GUI实现分布式

    什么是分布式: Jmeter的集群模式可以让我们将多台机器联合起来一起产生负载,从而弥补单台机器负载生成能力不足的问题. 假设我们的测试计划会产生100个threads,我们使用6台机器进行分布式测试 ...

  4. Jmeter报错之jmeter.gui.action.ActionRouter: Error processing gui.action.Start@1b7c473a java.lang.ArrayIndexOutOfBoundsException

    一个使用了很久的Jmeter脚本,运行时Jmeter的UI界面上点击绿色按钮后,完全无反应,只有log报错,如下: 2017/06/28 14:29:23 ERROR - jmeter.gui.act ...

  5. JMeter博客系列:JMeter BeanShell示例

    1.简介 Apache JMeter是一个基于Java的开源工具,使您可以在应用程序上执行功能,负载,性能和回归测试.应用程序可以在Web服务器上运行,也可以是独立的.它支持在包含静态和动态资源的客户 ...

  6. 一、Jmeter启动报错:Could not initialize class org.apache.jmeter.gui.util.MenuFactory

    1.下载: plugins-manager.jar 包 2.地址:https://jmeter-plugins.org/install/Install/ 3.将jar包放到lib/ext 4.重启jm ...

  7. 【JMeter_03】JMeter GUI操作界面介绍

    JMeter主界面主要分为 标题栏.菜单栏.工具栏.测试计划树形目录.内容展示区 标题栏:主要展示JMeter的程序版本.当前脚本的名称.脚本的储存路径 菜单栏:程序基本上所有功能的所属分类目录,基本 ...

  8. JMeter中各种请求格式--aduocd的博客

    背景:1.在JMeter的HTTP请求的测试中,经常会使用到不同的请求格式.常用的格式如,json,form-data,x-www-form-urlencoded,multipart/form-dat ...

  9. 【技术博客】 利用Postman和Jmeter进行接口性能测试

    利用Postman和Jmeter进行接口性能测试 作者:ZBW 版本:v1.1 在Phylab的开发过程中,对于生成报告接口的性能考量十分重要.原有的Latex接口虽然生成的报告美观,但编译Latex ...

随机推荐

  1. Oracle 查询 in条件个数大于1000的解决方案

    Oracle 查询 in条件个数大于1000的解决方案,我所了解的有如下四种: 1. 把in分组再or: 思路:如果list的长度为2000,可以500个分一组,就有4个组,这4个组之间再or即可. ...

  2. 43. Multiply Strings (JAVA)

    Given two non-negative integers num1 and num2represented as strings, return the product of num1 and  ...

  3. Nginx设置上传文件大小限制

    就是nginx对上传的图片大小有了限制嘛,所以更改nginx的配置文件就好了 client_max_body_size 1000m; 参考:https://blog.csdn.net/TitanSee ...

  4. octave-bug - 报告 GNU Octave 中的 bug

    SYNOPSIS 总览 octave-bug [-s subject] DESCRIPTION 描述 octave-bug 是一个 shell 脚本,用于以一种标准的格式撰写有关 Octave 的 b ...

  5. IPv6地址格式示例及IPv6与IPv4的区别分析

    认识IPv6地址 IPv4地址是类似 A.B.C.D 的格式,它是32位,用\".\"分成四段,用10进制表示: 而IPv6地址类似X:X:X:X:X:X:X:X的格式,它是128 ...

  6. fpga配置方式 .jic固化为ps模式

    FPGA不同下载方式的区别[扫盲]以及如何利用AS模式固化程序(转载)     主动配置方式(AS)和被动配置方式(PS)和最常用的(JTAG)配置方式: AS由FPGA器件引导配置操作过程,它控制着 ...

  7. dos2unix 将DOS格式转换成NUIX格式

    1.命令功能 dos2unix将windows文件格式转换成unix文件格式. 2.语法格式 dos2unix  file 3.使用范例 [root@localhost ~]# dos2unix wi ...

  8. uoj280 【UTR #2】题目难度提升 堆维护中位数+set

    题目传送门 http://uoj.ac/problem/280 题解 这道题很妙啊. 这种题目如果给予选手足够的时间,每一个选手应该都能做出来. 大概就是核心思路看上去很简单,但是想要推出来并不简单. ...

  9. linux下安装MySQL(mariadb)

    MySQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可. 开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源 ...

  10. 【leetcode】1128. Number of Equivalent Domino Pairs

    题目如下: Given a list of dominoes, dominoes[i] = [a, b] is equivalent to dominoes[j] = [c, d] if and on ...