001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.pool.performance;
019    
020    import org.apache.commons.pool.impl.GenericObjectPool;
021    
022    /**
023     * Multi-thread performance test
024     * 
025     * @author Dirk Verbeeck
026     * @version $Revision: 775703 $ $Date: 2009-05-17 12:39:51 -0400 (Sun, 17 May 2009) $ 
027     */
028    public class PerformanceTest {
029        private int logLevel = 0;
030        private int nrIterations = 5;
031    
032        private GenericObjectPool pool;
033        private boolean start = false;
034        private volatile int waiting = 0;
035        private volatile int complete = 0;
036        private volatile long totalBorrowTime = 0;
037        private volatile long totalReturnTime = 0;
038        private volatile int nrSamples = 0; 
039    
040        public void setLogLevel(int i) {
041            logLevel = i;
042        }
043        
044        private void init() {
045            start = false;
046            waiting = 0;
047            complete = 0;
048            totalBorrowTime = 0;
049            totalReturnTime = 0;
050            nrSamples = 0;     
051        }
052    
053        class MyThread implements Runnable {
054            long borrowTime;
055            long returnTime;
056    
057            public void runOnce() {
058                try {
059                    waiting++;
060                    if (logLevel >= 5) {
061                        String name = "thread" + Thread.currentThread().getName();
062                        System.out.println(name + "   waiting: " + waiting + "   complete: " + complete);
063                    }
064                    long bbegin = System.currentTimeMillis();
065                    Object o = pool.borrowObject();
066                    long bend = System.currentTimeMillis();
067                    waiting--;
068                    do {
069                        Thread.yield();
070                    }
071                    while (!start);
072    
073                    if (logLevel >= 3) {
074                        String name = "thread" + Thread.currentThread().getName();
075                        System.out.println(name + "    waiting: " + waiting + "   complete: " + complete);
076                    }
077                                     
078                    long rbegin = System.currentTimeMillis();
079                    pool.returnObject(o);
080                    long rend = System.currentTimeMillis();
081                    Thread.yield();
082                    complete++;
083                    borrowTime = (bend-bbegin);
084                    returnTime = (rend-rbegin);
085                } catch (Exception e) {
086                    e.printStackTrace();
087                }
088            }
089    
090            public void run() {
091                runOnce(); // warmup
092                for (int i = 0; i<nrIterations; i++) {
093                    runOnce();
094                    totalBorrowTime += borrowTime;
095                    totalReturnTime += returnTime;
096                    nrSamples++;
097                    if (logLevel >= 2) {
098                        String name = "thread" + Thread.currentThread().getName();
099                        System.out.println(
100                            "result " + nrSamples + "\t" + name 
101                            + "\t" + "borrow time: " + borrowTime + "\t" + "return time: " + returnTime
102                            + "\t" + "waiting: " + waiting + "\t" + "complete: " + complete);
103                    }
104                }
105            }
106        }
107    
108        private void run(int nrIterations, int nrThreads, int maxActive, int maxIdle) {
109            this.nrIterations = nrIterations;
110            init();
111            
112            SleepingObjectFactory factory = new SleepingObjectFactory();
113            if (logLevel >= 4) { factory.setDebug(true); } 
114            pool = new GenericObjectPool(factory);
115            pool.setMaxActive(maxActive);
116            pool.setMaxIdle(maxIdle);
117            pool.setTestOnBorrow(true);
118    
119            Thread[] threads = new Thread[nrThreads];
120            for (int i = 0; i < threads.length; i++) {
121                threads[i]= new Thread(new MyThread(), Integer.toString(i));
122                Thread.yield();
123            }
124            if (logLevel >= 1) { System.out.println("created"); } 
125            Thread.yield();
126    
127            for (int i = 0; i < threads.length; i++) {
128                threads[i].start();
129                Thread.yield();
130            }
131            if (logLevel >= 1) { System.out.println("started"); }
132            Thread.yield();
133    
134            start = true;
135            if (logLevel >= 1) { System.out.println("go"); }
136            Thread.yield();
137    
138            for (int i = 0; i < threads.length; i++) {
139                try {
140                    threads[i].join();
141                } catch (InterruptedException e) {
142                    e.printStackTrace();
143                }
144            }
145            if (logLevel >= 1) { System.out.println("finish"); }
146            System.out.println("-----------------------------------------");
147            System.out.println("nrIterations: " + nrIterations);
148            System.out.println("nrThreads: " + nrThreads);
149            System.out.println("maxActive: " + maxActive);
150            System.out.println("maxIdle: " + maxIdle);
151            System.out.println("nrSamples: " + nrSamples);
152            System.out.println("totalBorrowTime: " + totalBorrowTime);
153            System.out.println("totalReturnTime: " + totalReturnTime);
154            System.out.println("avg BorrowTime: " + totalBorrowTime/nrSamples);
155            System.out.println("avg ReturnTime: " + totalReturnTime/nrSamples);
156        }
157    
158        public static void main(String[] args) {
159            PerformanceTest test = new PerformanceTest();
160            test.setLogLevel(0);
161            System.out.println("Increase threads");
162            test.run(1,  50,  5,  5);
163            test.run(1, 100,  5,  5);
164            test.run(1, 200,  5,  5);
165            test.run(1, 400,  5,  5);
166    
167            System.out.println("Increase threads & poolsize");
168            test.run(1,  50,  5,  5);
169            test.run(1, 100, 10, 10);
170            test.run(1, 200, 20, 20);
171            test.run(1, 400, 40, 40);
172    
173            System.out.println("Increase maxIdle");
174            test.run(1, 400, 40,  5);
175            test.run(1, 400, 40, 40);
176    
177    
178    //      System.out.println("Show creation/destruction of objects");
179    //      test.setLogLevel(4);
180    //      test.run(1, 400, 40,  5);
181        }
182    
183    }