📄 tpcbexample.java
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1997-2006 * Oracle Corporation. All rights reserved. * * $Id: TpcbExample.java,v 12.8 2006/08/24 14:46:02 bostic Exp $ */package db;import com.sleepycat.db.*;import java.io.File;import java.io.FileNotFoundException;import java.math.BigDecimal;import java.util.Calendar;import java.util.Date;import java.util.Random;import java.util.GregorianCalendar;//// This program implements a basic TPC/B driver program. To create the// TPC/B database, run with the -i (init) flag. The number of records// with which to populate the account, history, branch, and teller tables// is specified by the a, s, b, and t flags respectively. To run a TPC/B// test, use the n flag to indicate a number of transactions to run in// each thread and -T to specify the number of threads.//class TpcbExample { public static final int TELLERS_PER_BRANCH = 10; public static final int ACCOUNTS_PER_TELLER = 10000; public static final int HISTORY_PER_BRANCH = 2592000; // // The default configuration that adheres to TPCB scaling rules requires // nearly 3 GB of space. To avoid requiring that much space for testing, // we set the parameters much lower. If you want to run a valid 10 TPS // configuration, uncomment the VALID_SCALING configuration // // VALID_SCALING configuration /* public static final int ACCOUNTS = 1000000; public static final int BRANCHES = 10; public static final int TELLERS = 100; public static final int HISTORY = 25920000; */ // TINY configuration /* public static final int ACCOUNTS = 1000; public static final int BRANCHES = 10; public static final int TELLERS = 100; public static final int HISTORY = 10000; */ // Default configuration public static final int ACCOUNTS = 100000; public static final int BRANCHES = 10; public static final int TELLERS = 100; public static final int HISTORY = 259200; public static final int HISTORY_LEN = 100; public static final int RECLEN = 100; public static final int BEGID = 1000000; // used by random_id() public static final int ACCOUNT = 0; public static final int BRANCH = 1; public static final int TELLER = 2; public static boolean verbose = false; public static final String progname = "TpcbExample"; // Program name. Environment dbenv; int accounts, branches, tellers, history; public TpcbExample(File home, int accounts, int branches, int tellers, int history, int cachesize, boolean noSync) throws DatabaseException, FileNotFoundException { this.accounts = accounts; this.branches = branches; this.tellers = tellers; this.history = history; EnvironmentConfig config = new EnvironmentConfig(); config.setErrorStream(System.err); config.setErrorPrefix(progname); config.setCacheSize(cachesize == 0 ? 4 * 1024 * 1024 : cachesize); config.setTxnNoSync(noSync); config.setLockDetectMode(LockDetectMode.DEFAULT); config.setAllowCreate(true); config.setInitializeCache(true); config.setTransactional(true); config.setInitializeLocking(true); config.setInitializeLogging(true); dbenv = new Environment(home, config); } public void close() throws DatabaseException { try { if (dbenv != null) dbenv.close(); } finally { dbenv = null; } } // // Initialize the database to the number of accounts, branches, // history records, and tellers given to the constructor. // public void populate() { Database dbp = null; int err; int balance, idnum; int end_anum, end_bnum, end_tnum; int start_anum, start_bnum, start_tnum; int h_nelem; idnum = BEGID; balance = 500000; h_nelem = accounts; try { DatabaseConfig config = new DatabaseConfig(); config.setType(DatabaseType.HASH); config.setHashNumElements(h_nelem); config.setAllowCreate(true); dbp = dbenv.openDatabase(null, "account", null, config); } catch (Exception e1) { // can be DatabaseException or FileNotFoundException errExit(e1, "Open of account file failed"); } start_anum = idnum; populateTable(dbp, idnum, balance, h_nelem, "account"); idnum += h_nelem; end_anum = idnum - 1; try { dbp.close(); } catch (DatabaseException e2) { errExit(e2, "Account file close failed"); } if (verbose) System.out.println("Populated accounts: " + String.valueOf(start_anum) + " - " + String.valueOf(end_anum)); // // Since the number of branches is very small, we want to use very // small pages and only 1 key per page. This is the poor-man's way // of getting key locking instead of page locking. // h_nelem = (int)branches; try { DatabaseConfig config = new DatabaseConfig(); config.setType(DatabaseType.HASH); config.setHashNumElements(h_nelem); config.setHashFillFactor(1); config.setPageSize(512); config.setAllowCreate(true); dbp = dbenv.openDatabase(null, "branch", null, config); } catch (Exception e3) { // can be DatabaseException or FileNotFoundException errExit(e3, "Branch file create failed"); } start_bnum = idnum; populateTable(dbp, idnum, balance, h_nelem, "branch"); idnum += h_nelem; end_bnum = idnum - 1; try { dbp.close(); } catch (DatabaseException dbe4) { errExit(dbe4, "Close of branch file failed"); } if (verbose) System.out.println("Populated branches: " + String.valueOf(start_bnum) + " - " + String.valueOf(end_bnum)); // // In the case of tellers, we also want small pages, but we'll let // the fill factor dynamically adjust itself. // h_nelem = (int)tellers; try { DatabaseConfig config = new DatabaseConfig(); config.setType(DatabaseType.HASH); config.setHashNumElements(h_nelem); config.setHashFillFactor(0); config.setPageSize(512); config.setAllowCreate(true); dbp = dbenv.openDatabase(null, "teller", null, config); } catch (Exception e5) { // can be DatabaseException or FileNotFoundException errExit(e5, "Teller file create failed"); } start_tnum = idnum; populateTable(dbp, idnum, balance, h_nelem, "teller"); idnum += h_nelem; end_tnum = idnum - 1; try { dbp.close(); } catch (DatabaseException e6) { errExit(e6, "Close of teller file failed"); } if (verbose) System.out.println("Populated tellers: " + String.valueOf(start_tnum) + " - " + String.valueOf(end_tnum)); try { DatabaseConfig config = new DatabaseConfig(); config.setType(DatabaseType.RECNO); config.setRecordLength(HISTORY_LEN); config.setAllowCreate(true); dbp = dbenv.openDatabase(null, "history", null, config); } catch (Exception e7) { // can be DatabaseException or FileNotFoundException errExit(e7, "Create of history file failed"); } populateHistory(dbp); try { dbp.close(); } catch (DatabaseException e8) { errExit(e8, "Close of history file failed"); } } public void populateTable(Database dbp, int start_id, int balance, int nrecs, String msg) { Defrec drec = new Defrec(); DatabaseEntry kdbt = new DatabaseEntry(drec.data); kdbt.setSize(4); // sizeof(int) DatabaseEntry ddbt = new DatabaseEntry(drec.data); ddbt.setSize(drec.data.length); // uses whole array try { for (int i = 0; i < nrecs; i++) { kdbt.setRecordNumber(start_id + (int)i); drec.set_balance(balance); dbp.putNoOverwrite(null, kdbt, ddbt); } } catch (DatabaseException dbe) { System.err.println("Failure initializing " + msg + " file: " + dbe.toString()); System.exit(1); } } public void populateHistory(Database dbp) { Histrec hrec = new Histrec(); hrec.set_amount(10); byte[] arr = new byte[4]; // sizeof(int) int i; DatabaseEntry kdbt = new DatabaseEntry(arr); kdbt.setSize(arr.length); DatabaseEntry ddbt = new DatabaseEntry(hrec.data); ddbt.setSize(hrec.data.length); try { for (i = 1; i <= history; i++) { kdbt.setRecordNumber(i); hrec.set_aid(random_id(ACCOUNT)); hrec.set_bid(random_id(BRANCH)); hrec.set_tid(random_id(TELLER)); dbp.append(null, kdbt, ddbt); } } catch (DatabaseException dbe) { errExit(dbe, "Failure initializing history file"); } } static Random rand = new Random(); public static int random_int(int lo, int hi) { int t = rand.nextInt(); if (t < 0) t = -t; int ret = (int)(((double)t / ((double)(Integer.MAX_VALUE) + 1)) * (hi - lo + 1)); ret += lo; return (ret); } public int random_id(int type) { int min, max, num; max = min = BEGID; num = accounts; switch(type) { case TELLER: min += branches; num = tellers; // fallthrough case BRANCH: if (type == BRANCH) num = branches; min += accounts; // fallthrough case ACCOUNT: max = min + num - 1; } return (random_int(min, max)); } // The byte order is our choice. // static long get_int_in_array(byte[] array, int offset) { return ((0xff & array[offset + 0]) << 0) | ((0xff & array[offset + 1]) << 8) | ((0xff & array[offset + 2]) << 16) | ((0xff & array[offset + 3]) << 24); } // Note: Value needs to be long to avoid sign extension static void set_int_in_array(byte[] array, int offset, long value) { array[offset + 0] = (byte)((value >> 0) & 0xff); array[offset + 1] = (byte)((value >> 8) & 0xff); array[offset + 2] = (byte)((value >> 16) & 0xff); array[offset + 3] = (byte)((value >> 24) & 0xff); } // round 'd' to 'scale' digits, and return result as string static String showRounded(double d, int scale) { return new BigDecimal(d). setScale(scale, BigDecimal.ROUND_HALF_DOWN).toString(); } public void run(int ntxns, int threads) { double gtps; int txns, failed; long curtime, starttime; TxnThread[] txnList = new TxnThread[threads]; for (int i = 0; i < threads; i++) txnList[i] = new TxnThread("Thread " + String.valueOf(i), ntxns); starttime = (new Date()).getTime(); for (int i = 0; i < threads; i++) txnList[i].start(); for (int i = 0; i < threads; i++) try { txnList[i].join(); } catch (Exception e1) { errExit(e1, "join failed"); } curtime = (new Date()).getTime(); txns = failed = 0; for (int i = 0; i < threads; i++) { txns += txnList[i].txns; failed += txnList[i].failed; } gtps = (double)(txns - failed) / ((curtime - starttime) / 1000.0); System.out.print("\nTotal: " + String.valueOf(txns) + " txns " + String.valueOf(failed) + " failed "); System.out.println(showRounded(gtps, 2) + " TPS"); } class TxnThread extends Thread { private int ntxns; /* Number of txns we were asked to run. */ public int txns, failed; /* Number that succeeded / failed. */ private Database adb, bdb, hdb, tdb; public TxnThread(String name, int ntxns) { super(name); this.ntxns = ntxns; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -