Optimizing an Oracle Database for an e-commerce service

In this example study, we will tune the initialization parameters of an Oracle Database server instance to minimize the memory required for running KonaKart, a popular Java e-commerce service, without significantly impacting the responsiveness of the whole system.

We’ll use Apache JMeter to stress the system for the test, while we will leverage the Oracle Prometheus exporter to extract the metrics.

Environment Setup

Environment

For this study, we will use three dedicated machines:

  • oradb.mycompany.com, hosting an Oracle Database 19c instance

  • konakart.mycompany.com, running the KonaKart Community Edition service

  • akamas.mycompany.com, which generates the workload using JMeter and will host the OracleDB Prometheus exporter instance

Refer to the following links to install and configure KonaKart Community Edition:

For this use case, we provisioned the database on a VM on Oracle Cloud, which allows us to easily provision licensed instances on demand.

Prometheus and exporters

Install the OracleDB Prometheus exporter

Through the OracleDB Prometheus exporter, we can publish as metrics the results of the arbitrary queries defined in the configuration file. In our case, we’ll use it to extract valuable performance metrics from Oracle’s Dynamic Performance (V$) Views.

We can spin up the exporter using the official Docker image using the following command, where cust-metrics.toml is our custom metrics file:

docker run -d --name orabench_exporter --restart always \
  -p 9161:9161 \
  -v ~/oracledb_exporter/cust-metrics.toml:/cust-metrics.toml \
  -e CUSTOM_METRICS=/cust-metrics.toml \
  -e DATA_SOURCE_NAME='user/passwd@//oradb.mycompany.com:1521/konakart' \
  iamseth/oracledb_exporter

The exporter will publish the metrics on the specified port 9161.

Here’s the metrics file used to run the exporter:

[[metric]]
context= "memory"
labels= [ "component" ]
metricsdesc= { size="Component memory extracted from v$memory_dynamic_components in Oracle." }
request = '''
SELECT component, current_size as "size"
FROM V$MEMORY_DYNAMIC_COMPONENTS
UNION
SELECT name, bytes as "size"
FROM V$SGAINFO
WHERE name in ('Free SGA Memory Available', 'Redo Buffers', 'Maximum SGA Size')
'''

[[metric]]
context = "activity"
metricsdesc = { value="Generic counter metric from v$sysstat view in Oracle." }
fieldtoappend = "name"
request = '''
SELECT name, value
FROM V$SYSSTAT WHERE name IN (
  'execute count',
  'user commits', 'user rollbacks',
  'db block gets from cache', 'consistent gets from cache', 'physical reads cache', /* CACHE */
  'redo log space requests'
 )
 '''

[[metric]]
context = "system_event"
labels = [ "event", "wait_class" ]
request = '''
SELECT
  event, wait_class,
  total_waits, time_waited
FROM V$SYSTEM_EVENT
'''
[metric.metricsdesc]
  total_waits= "Total number of waits for the event as per V$SYSTEM_EVENT in Oracle."
  time_waited= "Total time waited for the event (in hundredths of seconds) as per V$SYSTEM_EVENT in Oracle."

Install and configure Prometheus

Using the following snippet we configure Prometheus to fetch metrics from:

  • the JMeter exporter exposing the load-generator stats

  • the OracleDB exporter monitoring the database

scrape_configs:
  - job_name: jmeter
    static_configs:
      - targets: ['akamas.mycompany.com:9270']
    relabel_configs:
      - source_labels: [__address__]
        action: replace
        regex: "(.*):.*"
        target_label: instance

  - job_name: oracle-exp
    static_configs:
      - targets: ['akamas.mycompany.com:9161']
        labels:
          instance: oradb

For a complete guide on how to configure and manage Prometheus refer to the official documentation.

Setup the load-generator

The load generator runs containerized on the akamas.mycomopany.com instance using the attached Konakart_optimizePerf.jmx configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.3">
  <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 name="HOST" elementType="Argument">
            <stringProp name="Argument.name">HOST</stringProp>
            <stringProp name="Argument.value">${__P(HOST,konakartoraclecloud.lab.akamas.io)}</stringProp>
            <stringProp name="Argument.metadata">=</stringProp>
          </elementProp>
          <elementProp name="VUSER" elementType="Argument">
            <stringProp name="Argument.name">VUSER</stringProp>
            <stringProp name="Argument.value">${__P(VUSER,60)}</stringProp>
            <stringProp name="Argument.metadata">=</stringProp>
          </elementProp>
        </collectionProp>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <kg.apc.jmeter.threads.UltimateThreadGroup guiclass="kg.apc.jmeter.threads.UltimateThreadGroupGui" testclass="kg.apc.jmeter.threads.UltimateThreadGroup" testname=" Thread Group" enabled="true">
        <collectionProp name="ultimatethreadgroupdata">
          <collectionProp name="682260423">
            <stringProp name="-1375672883">${__P(VUSER,10)}</stringProp>
            <stringProp name="0">0</stringProp>
            <stringProp name="49586">200</stringProp>
            <stringProp name="53430">600</stringProp>
            <stringProp name="48">0</stringProp>
          </collectionProp>
        </collectionProp>
        <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.on_sample_error">startnextloop</stringProp>
      </kg.apc.jmeter.threads.UltimateThreadGroup>
      <hashTree>
        <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random catId" enabled="true">
          <stringProp name="maximumValue">30</stringProp>
          <stringProp name="minimumValue">1</stringProp>
          <stringProp name="outputFormat"></stringProp>
          <boolProp name="perThread">true</boolProp>
          <stringProp name="randomSeed">666</stringProp>
          <stringProp name="variableName">catId</stringProp>
        </RandomVariableConfig>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Welcome" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">${HOST}</stringProp>
          <stringProp name="HTTPSampler.port">8780</stringProp>
          <stringProp name="HTTPSampler.protocol">http</stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">konakart/Welcome.action</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">true</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp>
          <boolProp name="HTTPSampler.image_parser">true</boolProp>
          <boolProp name="HTTPSampler.concurrentDwn">true</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SelectCat" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">${HOST}</stringProp>
          <stringProp name="HTTPSampler.port">8780</stringProp>
          <stringProp name="HTTPSampler.protocol">http</stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">konakart/SelectCat.action?catId=${catId}</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">true</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp>
          <boolProp name="HTTPSampler.image_parser">true</boolProp>
          <boolProp name="HTTPSampler.concurrentDwn">true</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <com.github.johrstrom.listener.PrometheusListener guiclass="com.github.johrstrom.listener.gui.PrometheusListenerGui" testclass="com.github.johrstrom.listener.PrometheusListener" testname="Prometheus Listener" enabled="true">
          <collectionProp name="prometheus.collector_definitions">
            <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
              <stringProp name="collector.help">Sampler Response Time</stringProp>
              <stringProp name="collector.metric_name">ResponseTime</stringProp>
              <stringProp name="collector.type">SUMMARY</stringProp>
              <collectionProp name="collector.labels">
                <stringProp name="102727412">label</stringProp>
                <stringProp name="3059181">code</stringProp>
              </collectionProp>
              <stringProp name="collector.quantiles_or_buckets">0.5,0.01|0.85,0.01|0.9,0.01|0.99,0.01;60</stringProp>
              <stringProp name="listener.collector.listen_to">samples</stringProp>
              <stringProp name="listener.collector.measuring">ResponseTime</stringProp>
            </elementProp>
            <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
              <stringProp name="collector.help">Success and failure ratio</stringProp>
              <stringProp name="collector.metric_name">Ratio</stringProp>
              <stringProp name="collector.type">SUCCESS_RATIO</stringProp>
              <collectionProp name="collector.labels">
                <stringProp name="102727412">label</stringProp>
                <stringProp name="3059181">code</stringProp>
              </collectionProp>
              <stringProp name="collector.quantiles_or_buckets"></stringProp>
              <stringProp name="listener.collector.listen_to">samples</stringProp>
              <stringProp name="listener.collector.measuring">SuccessRatio</stringProp>
            </elementProp>
          </collectionProp>
        </com.github.johrstrom.listener.PrometheusListener>
        <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="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/>
      </hashTree>
      <kg.apc.jmeter.threads.UltimateThreadGroup guiclass="kg.apc.jmeter.threads.UltimateThreadGroupGui" testclass="kg.apc.jmeter.threads.UltimateThreadGroup" testname="jp@gc - Ultimate Thread Group - slow slope" enabled="false">
        <collectionProp name="ultimatethreadgroupdata">
          <collectionProp name="-811668396">
            <stringProp name="50">2</stringProp>
            <stringProp name="48">0</stringProp>
            <stringProp name="1722">60</stringProp>
            <stringProp name="1508508">1140</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
          <collectionProp name="1110318546">
            <stringProp name="50">2</stringProp>
            <stringProp name="50547">300</stringProp>
            <stringProp name="1722">60</stringProp>
            <stringProp name="55476">840</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
          <collectionProp name="-277728215">
            <stringProp name="50">2</stringProp>
            <stringProp name="53430">600</stringProp>
            <stringProp name="1722">60</stringProp>
            <stringProp name="52593">540</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
          <collectionProp name="1889215593">
            <stringProp name="50">2</stringProp>
            <stringProp name="56313">900</stringProp>
            <stringProp name="1722">60</stringProp>
            <stringProp name="49710">240</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
        </collectionProp>
        <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.on_sample_error">continue</stringProp>
      </kg.apc.jmeter.threads.UltimateThreadGroup>
      <hashTree>
        <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random catId" enabled="true">
          <stringProp name="maximumValue">30</stringProp>
          <stringProp name="minimumValue">1</stringProp>
          <stringProp name="outputFormat"></stringProp>
          <boolProp name="perThread">true</boolProp>
          <stringProp name="randomSeed">666</stringProp>
          <stringProp name="variableName">catId</stringProp>
        </RandomVariableConfig>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Welcome" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">${__P(HOST,konakartoraclecloud.lab.akamas.io)}</stringProp>
          <stringProp name="HTTPSampler.port">8780</stringProp>
          <stringProp name="HTTPSampler.protocol">http</stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">konakart/Welcome.action</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">true</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp>
          <boolProp name="HTTPSampler.image_parser">true</boolProp>
          <boolProp name="HTTPSampler.concurrentDwn">true</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <TestAction guiclass="TestActionGui" testclass="TestAction" testname="think time" enabled="true">
          <intProp name="ActionProcessor.action">1</intProp>
          <intProp name="ActionProcessor.target">0</intProp>
          <stringProp name="ActionProcessor.duration">100</stringProp>
        </TestAction>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SelectCat" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">${__P(HOST,konakartoraclecloud.lab.akamas.io)}</stringProp>
          <stringProp name="HTTPSampler.port">8780</stringProp>
          <stringProp name="HTTPSampler.protocol">http</stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">konakart/SelectCat.action?catId=${catId}</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">true</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp>
          <boolProp name="HTTPSampler.image_parser">true</boolProp>
          <boolProp name="HTTPSampler.concurrentDwn">true</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <TestAction guiclass="TestActionGui" testclass="TestAction" testname="think time" enabled="true">
          <intProp name="ActionProcessor.action">1</intProp>
          <intProp name="ActionProcessor.target">0</intProp>
          <stringProp name="ActionProcessor.duration">100</stringProp>
        </TestAction>
        <hashTree/>
        <com.github.johrstrom.listener.PrometheusListener guiclass="com.github.johrstrom.listener.gui.PrometheusListenerGui" testclass="com.github.johrstrom.listener.PrometheusListener" testname="Prometheus Listener" enabled="true">
          <collectionProp name="prometheus.collector_definitions">
            <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
              <stringProp name="collector.help">Sampler Response Time</stringProp>
              <stringProp name="collector.metric_name">ResponseTime</stringProp>
              <stringProp name="collector.type">SUMMARY</stringProp>
              <collectionProp name="collector.labels">
                <stringProp name="102727412">label</stringProp>
                <stringProp name="3059181">code</stringProp>
              </collectionProp>
              <stringProp name="collector.quantiles_or_buckets">0.5,0.01|0.85,0.01|0.9,0.01|0.99,0.01;60</stringProp>
              <stringProp name="listener.collector.listen_to">samples</stringProp>
              <stringProp name="listener.collector.measuring">ResponseTime</stringProp>
            </elementProp>
            <elementProp name="" elementType="com.github.johrstrom.listener.ListenerCollectorConfig">
              <stringProp name="collector.help">Success and failure ratio</stringProp>
              <stringProp name="collector.metric_name">Ratio</stringProp>
              <stringProp name="collector.type">SUCCESS_RATIO</stringProp>
              <collectionProp name="collector.labels">
                <stringProp name="102727412">label</stringProp>
                <stringProp name="3059181">code</stringProp>
              </collectionProp>
              <stringProp name="collector.quantiles_or_buckets"></stringProp>
              <stringProp name="listener.collector.listen_to">samples</stringProp>
              <stringProp name="listener.collector.measuring">SuccessRatio</stringProp>
            </elementProp>
          </collectionProp>
        </com.github.johrstrom.listener.PrometheusListener>
        <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="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/>
      </hashTree>
      <kg.apc.jmeter.threads.UltimateThreadGroup guiclass="kg.apc.jmeter.threads.UltimateThreadGroupGui" testclass="kg.apc.jmeter.threads.UltimateThreadGroup" testname="jp@gc - Ultimate Thread Group  - steep slope" enabled="false">
        <collectionProp name="ultimatethreadgroupdata">
          <collectionProp name="-1293805452">
            <stringProp name="1696">55</stringProp>
            <stringProp name="48">0</stringProp>
            <stringProp name="50547">300</stringProp>
            <stringProp name="1507521">1035</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
          <collectionProp name="-1729043283">
            <stringProp name="52">4</stringProp>
            <stringProp name="52593">540</stringProp>
            <stringProp name="1598">20</stringProp>
            <stringProp name="54613">775</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
          <collectionProp name="110060986">
            <stringProp name="53">5</stringProp>
            <stringProp name="55352">800</stringProp>
            <stringProp name="1603">25</stringProp>
            <stringProp name="52500">510</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
          <collectionProp name="-1520762789">
            <stringProp name="54">6</stringProp>
            <stringProp name="1507614">1065</stringProp>
            <stringProp name="1629">30</stringProp>
            <stringProp name="49710">240</stringProp>
            <stringProp name="0"></stringProp>
          </collectionProp>
        </collectionProp>
        <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.on_sample_error">continue</stringProp>
      </kg.apc.jmeter.threads.UltimateThreadGroup>
      <hashTree>
        <RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="Random catId" enabled="true">
          <stringProp name="maximumValue">30</stringProp>
          <stringProp name="minimumValue">1</stringProp>
          <stringProp name="outputFormat"></stringProp>
          <boolProp name="perThread">true</boolProp>
          <stringProp name="randomSeed">666</stringProp>
          <stringProp name="variableName">catId</stringProp>
        </RandomVariableConfig>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Welcome" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">${__P(HOST,konakartoraclecloud.lab.akamas.io)}</stringProp>
          <stringProp name="HTTPSampler.port">8780</stringProp>
          <stringProp name="HTTPSampler.protocol">http</stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">konakart/Welcome.action</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">true</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.BROWSER_COMPATIBLE_MULTIPART">true</boolProp>
          <boolProp name="HTTPSampler.image_parser">true</boolProp>
          <boolProp name="HTTPSampler.concurrentDwn">true</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SelectCat" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">${__P(HOST,konakartoraclecloud.lab.akamas.io)}</stringProp>
          <stringProp name="HTTPSampler.port">8780</stringProp>
          <stringProp name="HTTPSampler.protocol">http</stringProp>