Commit:    66b3bbc82c844d16b58a296317ff2ccd0a048bc5
Author:    Matt Ficken <v-maf...@microsoft.com>         Tue, 17 Sep 2013 
12:47:12 -0700
Parents:   f3797cad42701eddd3a7232ed21dd8f864d10cb9
Branches:  master

Link:       
http://git.php.net/?p=pftt2.git;a=commitdiff;h=66b3bbc82c844d16b58a296317ff2ccd0a048bc5

Log:
thread pool support windows hack


Former-commit-id: fa5fe58f486b74da10fed3cb378077731e6131d4

Changed paths:
  M  src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
  M  src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java
  M  src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java
  M  src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
  M  src/com/mostc/pftt/util/TimerUtil.java

diff --git a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java 
b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
index bbe4a3d..1f9de53 100644
--- a/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
+++ b/src/com/mostc/pftt/runner/AbstractLocalTestPackRunner.java
@@ -180,7 +180,10 @@ public abstract class AbstractLocalTestPackRunner<A 
extends ActiveTestPack, S ex
                        return null;
                }
                //
-               cm.println(EPrintType.CLUE, getClass(), "Scenario Set: 
"+scenario_set_setup.getNameWithVersionInfo());
+               if (scenario_set_setup!=null)
+                       cm.println(EPrintType.CLUE, getClass(), "Scenario Set: 
"+scenario_set_setup.getNameWithVersionInfo());
+               else if (scenario_set!=null)
+                       cm.println(EPrintType.CLUE, getClass(), "Scenario Set: 
"+scenario_set.getName());
                setupStorageAndTestPack(storage_dir, test_cases);
                
                return storage_dir;
diff --git a/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java 
b/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java
index 6f9e8c4..7a82e66 100644
--- a/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/BuiltinWebHttpPhptTestCaseRunner.java
@@ -22,6 +22,7 @@ import com.mostc.pftt.results.ITestResultReceiver;
 import com.mostc.pftt.runner.LocalPhptTestPackRunner.PhptThread;
 import com.mostc.pftt.scenario.BuiltinWebServerScenario;
 import com.mostc.pftt.scenario.ScenarioSetSetup;
+import com.mostc.pftt.util.TimerUtil;
 
 public class BuiltinWebHttpPhptTestCaseRunner extends HttpPhptTestCaseRunner {
        
@@ -57,13 +58,13 @@ public class BuiltinWebHttpPhptTestCaseRunner extends 
HttpPhptTestCaseRunner {
                final Socket s = test_socket;
                if (s==null)
                        return;
-               new Thread() {
+               TimerUtil.runThread(new Runnable() {
                        public void run() {
                                try {
                                s.close();
                                } catch ( Exception ex ) {}
                        }
-               };
+               });
                test_socket = null;
        }
        
diff --git a/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java 
b/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java
index fafcd4f..3390bfc 100644
--- a/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java
+++ b/src/com/mostc/pftt/runner/HttpPhptTestCaseRunner.java
@@ -304,13 +304,13 @@ public class HttpPhptTestCaseRunner extends 
AbstractPhptTestCaseRunner2 {
                final Socket s = test_socket;
                if (s==null)
                        return;
-               new Thread() {
+               TimerUtil.runThread(new Runnable() {
                        public void run() {
                                try {
                                s.close();
                                } catch ( Exception ex ) {}
                        }
-               };
+               });
                test_socket = null;
        }
        
diff --git a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java 
b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
index 287a955..2f4f55c 100644
--- a/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
+++ b/src/com/mostc/pftt/scenario/BuiltinWebServerScenario.java
@@ -65,12 +65,12 @@ public class BuiltinWebServerScenario extends 
WebServerScenario {
        @Override
        public int getApprovedInitialThreadPoolSize(AHost host, int threads) {
                // XXX update this calculation from time to time as this web 
server's performance improves (probably decrease number)
-               return host.getCPUCount() * 6;//8;
+               return host.getCPUCount() * 4;
        }
        
        @Override
        public int getApprovedMaximumThreadPoolSize(AHost host, int threads) {
-               return host.getCPUCount() * 8;// TODO 10;
+               return host.getCPUCount() * 6;
        }
        
        @Override
diff --git a/src/com/mostc/pftt/util/TimerUtil.java 
b/src/com/mostc/pftt/util/TimerUtil.java
index cd5dc70..cfe073b 100644
--- a/src/com/mostc/pftt/util/TimerUtil.java
+++ b/src/com/mostc/pftt/util/TimerUtil.java
@@ -1,11 +1,104 @@
 package com.mostc.pftt.util;
 
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.LinkedList;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import com.mostc.pftt.host.LocalHost;
 import com.mostc.pftt.results.ConsoleManager;
 
 public final class TimerUtil {
+        
+       private static LinkedList<ThreadRunnableProxy> trp_pool = new 
LinkedList<ThreadRunnableProxy>();
+       static {
+               final int pool_size = Math.max(128, new 
LocalHost().getCPUCount() * 16);
+               for ( int i = 0 ; i < pool_size ; i++ ) {
+                       ThreadRunnableProxy trp = new ThreadRunnableProxy();
+                       new Thread(trp).start();
+                               synchronized(trp_pool) {
+                                       trp_pool.add(trp);
+                               }
+               }
+       }
+       
+       private static class ThreadRunnableProxy implements Runnable {
+               private Runnable r;
+               private final Object lock = new Object();
+               private Thread thread;
+               private boolean run = true;
+               
+               private void setRunnable(Runnable r) {
+                       this.r = r;
+                       synchronized(lock) {
+                               lock.notify();
+                       }
+               }
+               
+               @SuppressWarnings("unused")
+               private void stop() {
+                       run = false;
+               }
+               
+               public void run() {
+                       thread = Thread.currentThread();
+                       while(run) {
+                               if (r!=null) {
+                                       try {
+                                               r.run();
+                                       } catch (Throwable t) {
+                                               
thread.getUncaughtExceptionHandler().uncaughtException(thread, t);
+                                       }
+                                       r = null;
+                                       synchronized(trp_pool) {
+                                               trp_pool.add(this);
+                                       }
+                               }
+                               try {
+                                       synchronized(lock) {
+                                               lock.wait();
+                                       }
+                               } catch ( Throwable t ) {
+                                       try {
+                                               Thread.sleep(100);
+                                       } catch ( InterruptedException i ) {}
+                               }
+                       }
+               }
+       } // end private static class ThreadRunnableProxy
+       
+       /** Windows, at least, has problems creating threads late in some test 
runs sometimes.
+        * 
+        * Creating a thread requires getting a handle, and sometimes if 
Windows has allocated too
+        * many handles, it will wait a long time before allocating more, which 
delays thread creation
+        * (which in turn can delay things like killing off timed out 
processes, which in turn frees up handles).
+        * 
+        * Instead, a bunch of threads are preallocated in a pool at startup. 
This gets one of
+        * those threads and has it run the given Runnable.
+        * 
+        * Note: you may not call #start or #setDaemon on the returned Thread. 
you will get an IllegalThreadStateException if you do.
+        * 
+        * @param r
+        * @return
+        */
+       public static Thread runThread(Runnable r) {
+               ThreadRunnableProxy trp = null;
+               synchronized(trp_pool) {
+                       if (!trp_pool.isEmpty())
+                               trp = trp_pool.removeLast();
+               }
+               if (trp==null) {
+                       return new Thread(r);
+               } else {
+                       trp.setRunnable(r);
+                       return trp.thread;
+               }
+       }
+       
+       public static Thread runThread(String prefix, Runnable r) {
+               Thread t = runThread(r);
+               t.setName(prefix);
+               return t;
+       }
        
        public interface ObjectRunnable<E extends Object> {
                E run() throws Exception;
@@ -19,12 +112,9 @@ public final class TimerUtil {
        
        public static <E extends Object> WaitableRunnable<E> 
runWaitSeconds(String name_prefix, int seconds, ObjectRunnable<E> or) {
                WaitableRunnable<E> wr = new WaitableRunnable<E>(or);
-               Thread t = new Thread(wr);
+               Thread t = runThread(name_prefix, wr);
                t.setUncaughtExceptionHandler(IGNORE);
-               t.setDaemon(true);
-               t.setName(name_prefix+t.getName());
                wr.t = t;
-               t.start();
                wr.block(seconds);
                return wr;
        }
@@ -111,10 +201,14 @@ public final class TimerUtil {
        public interface RepeatingRunnable {
                public void run(RepeatingThread thread);
        }
+       
+       protected static void createRThread(RepeatingOrTimingThread t) {
+               t.t = runThread("Timer", (Runnable)t);
+       }
 
        public static RepeatingThread repeatEverySeconds(int seconds, 
RepeatingRunnable r) {
                RepeatingThread t = new RepeatingThread(seconds, r);
-               t.start();
+               createRThread(t);
                return t;
        }
        
@@ -148,7 +242,7 @@ public final class TimerUtil {
                } else {
                        t = new TimerThread2SX(seconds1, r1, seconds2, 
runnables2);
                }
-               t.start();
+               createRThread(t);
                return t;
        }
        
@@ -178,11 +272,11 @@ public final class TimerUtil {
                
                @Override
                protected void fire2() {
-                       new Thread() {
+                       runThread(new Runnable() {
                                public void run() {
                                        b2.run();
                                }
-                       }.start();
+                       });
                        a2.run();
                }
                
@@ -203,12 +297,12 @@ public final class TimerUtil {
                        
                        for ( int i=1 ; i < runnables2.length ; i++ ) {
                                final Runnable r = runnables2[i];
-                               new Thread() {
+                               runThread(new Runnable() {
                                                @Override
                                                public void run() {
                                                        r.run();
                                                }
-                                       }.start();
+                                       });
                        }
                        runnables2[0].run();
                }
@@ -267,7 +361,7 @@ public final class TimerUtil {
                } else {
                        t = new TimerThreadX(seconds, runnables);
                }
-               t.start();
+               createRThread(t);
                return t;
        }
        
@@ -297,11 +391,11 @@ public final class TimerUtil {
                
                @Override
                protected void fire() {
-                       new Thread() {
+                       runThread(new Runnable() {
                                public void run() {
                                        b.run();
                                }
-                       }.start();
+                       });
                        a.run();
                }
                
@@ -322,12 +416,12 @@ public final class TimerUtil {
                        
                        for ( int i=1 ; i < runnables.length ; i++ ) {
                                final Runnable r = runnables[i];
-                               new Thread() {
+                               runThread(new Runnable() {
                                                @Override
                                                public void run() {
                                                        r.run();
                                                }
-                                       }.start();
+                                       });
                        }
                        runnables[0].run();
                }
@@ -361,24 +455,23 @@ public final class TimerUtil {
                
        }
        
-       protected static class RepeatingOrTimingThread extends Thread 
implements IClosable {
+       protected static abstract class RepeatingOrTimingThread implements 
Runnable, IClosable {
                protected final int seconds;
                protected final AtomicBoolean b, sleeping;
+               protected Thread t;
                
                public RepeatingOrTimingThread(int seconds) {
                        this.seconds = seconds;
                        
                        b = new AtomicBoolean(false);
                        sleeping = new AtomicBoolean(false);
-                       setName("Timer"+getName());
-                       setDaemon(true);
                }
                
                public void close() {
                        b.set(true);
                        if (sleeping.get()) {
                                // interrupt #sleep not #fire
-                               RepeatingOrTimingThread.this.interrupt();
+                               t.interrupt();
                        }
                }

Reply via email to