DayTrader 7 is designed first and foremost as a performance benchmark tool. Raw throughput numbers are only meaningful when the environment is controlled: resource contention from a co-located database or load driver will skew results, an untuned DB2 instance will bottleneck before the JVM does, and an un-warmed JIT compiler will make the first measurement run look worse than subsequent ones. Producing credible, repeatable numbers requires a dedicated three-machine topology, DB2 (not the embedded Derby instance), specific server tuning, and a disciplined run procedure.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/WASdev/sample.daytrader7/llms.txt
Use this file to discover all available pages before exploring further.
Benchmark topology
Separate your benchmark environment across three dedicated machines to avoid cross-component resource contention:| Machine | Role |
|---|---|
| Open Liberty machine | Runs the DayTrader application server (Open Liberty) |
| DB2 machine | Runs the IBM DB2 database (tradedb) |
| Driver machine | Runs Apache JMeter and the WebSocket Samplers plugin |
Pre-benchmark checklist
Complete every step below once, before your first measurement run. The database backup created in step 6 is restored before each subsequent server start.Build the application
Clone or download the repository, then build from the project root:This produces
daytrader-ee7/target/daytrader-ee7.ear. Copy it to your Liberty server’s apps directory:Configure Open Liberty with DB2
Copy the DB2-ready server configuration (overwriting the default Set the following environment variables so Liberty can reach your DB2 instance, or hard-code them directly in
server.xml):server.xml:Copy DB2 JDBC drivers
Copy the DB2 JDBC JAR files from the DB2 machine to the Liberty shared resources directory. Both JARs are required:Place them in:This path matches the
<fileset dir="${shared.resource.dir}/db2jars" ...> element in server_db2.xml.Set JVM heap options
Create Setting the initial and maximum heap to the same value eliminates GC-driven heap growth events during a measurement window.
<OPENLIBERTY_HOME>/usr/servers/defaultServer/jvm.options and add at minimum:Create the database and initialize data
On the DB2 machine, sign in as the Start Open Liberty, then navigate to the configuration page in a browser:Click “(Re)-create DayTrader Database Tables and Indexes”, then click “(Re)-populate DayTrader Database”. This creates 15,000 users (
db2 user and create the database. If DB2_APM_PERFORMANCE is enabled you will encounter error SQL1803N — disable it first:uid:0 – uid:14999) and 10,000 stock symbols (s:0 – s:9999).Once population is complete, stop Liberty:Create a DB2 backup after population
On the DB2 machine, save a clean snapshot of the populated database. This backup is the baseline that you restore before every measurement run:
If disk I/O becomes a bottleneck during restore, consider creating a RAM disk and restoring the database onto it. Fast restore latency matters because it directly gates how quickly you can cycle between runs.
Apply DB2 performance tuning
Put the following into a script (e.g., Key settings and their rationale:
backupTradeDB.sh) and run it as the db2 user. It applies recommended performance settings and then creates the backup from step 6:| Parameter | Value | Purpose |
|---|---|---|
LOCKLIST | 100000 | Enlarges the lock list to reduce lock escalation under high concurrency |
LOGFILSIZ | 8000 | Large log files reduce I/O frequency during write-heavy workloads |
BUFFPAGE | 262144 | Maximizes the buffer pool to keep more data pages in memory |
MAXLOCKS | 100 | Percentage of lock list a single application can consume before escalation |
NUM_POOLAGENTS | 500 | Sufficient agent pool for 100+ Liberty connection pool threads |
DB2_KEEPTABLELOCK | CONNECTION | Reduces row-level lock overhead for DayTrader’s update-heavy pattern |
Run procedure
Follow this sequence for every measurement session. The database restore ensures that each run starts from an identical data state, which is essential for comparing results across different configuration options. Before each server start, restore the database on the DB2 machine as thedb2 user:
The reset removes all users registered during the run (those with the
ru: prefix) and marks outstanding orders as completed. Skipping the reset means successive runs operate on a progressively larger database, making results non-comparable.TradeScenario workload mix
TheTradeScenarioServlet (URL: /daytrader/scenario) emulates a population of users by selecting a random trade operation on each HTTP request. The mix is defined in TradeConfig.java and determines what percentage of requests exercise each operation path.
Standard mix (default):
| Operation constant | Action | Standard mix | High-volume mix |
|---|---|---|---|
HOME_OP | Display market summary home page | 20 % | 20 % |
QUOTE_OP | Look up a stock quote | 40 % | 40 % |
LOGIN_OP | Log in (always 0 — handled implicitly by LOGOUT_OP) | 0 % | 0 % |
LOGOUT_OP | Log out (triggers a new login on the next request) | 4 % | 4 % |
REGISTER_OP | Register a new user | 2 % | 2 % |
ACCOUNT_OP | View account details | 10 % | 7 % |
PORTFOLIO_OP | View user portfolio | 12 % | 7 % |
BUY_OP | Buy stock | 4 % | 7 % |
SELL_OP | Sell stock | 4 % | 7 % |
UPDATEACCOUNT_OP | Update account profile | 4 % | 6 % |
Key configuration parameters
These parameters, set via the DayTrader configuration page orserver.xml, have the largest effect on benchmark results. Change only one at a time when comparing measurements.
| Parameter | Options / Value | Effect |
|---|---|---|
runTimeMode | EJB3 (default) | Direct (JDBC) | Selects whether trading operations use the EJB 3 container or bypass it with direct JDBC and JMS code. Direct mode isolates the JDBC/JMS path; EJB3 exercises the full EJB container stack. |
orderProcessingMode | Sync | Async_2-Phase | Async_ManagedThread | Controls how stock buy/sell orders are completed. Sync completes orders immediately in the request thread. Async_2-Phase queues orders to TradeBrokerMDB with a two-phase commit over EJB and JMS. Async_ManagedThread uses the Java EE 7 Concurrency Utilities ManagedThreadFactory. |
maxPoolSize | 100 (in server.xml) | JDBC connection pool size for the TradeDataSource. Set equal to or higher than the JMeter thread count to avoid connection wait time masking application throughput. |
maxKeepAliveRequests | -1 (unlimited, in server.xml) | Allows HTTP keep-alive connections to persist indefinitely, avoiding TCP handshake overhead per request during a JMeter run. |
server_db2.xml ships with maxPoolSize=100 and maxKeepAliveRequests=-1 already configured:
Next steps
JMeter Load Testing
Configure the DayTrader JMeter test plans, set command-line parameters, and enable real-time output.
Web Primitives
Isolate individual Java EE component performance with DayTrader’s built-in micro-benchmark servlets.