Coverage Report - org.paneris.bibliomania.loadtest.LoadTest
 
Classes in this File Line Coverage Branch Coverage Complexity
AuthorLevel
0%
0/3
N/A
1.353
BitBucket
0%
0/16
0%
0/2
1.353
BookLevel
0%
0/3
N/A
1.353
ChapterLevel
0%
0/4
N/A
1.353
ExponentialDistribution
0%
0/7
0%
0/2
1.353
HitStats
0%
0/9
0%
0/4
1.353
Level
0%
0/2
N/A
1.353
LoadTest
0%
0/46
0%
0/6
1.353
LoadTest$1
N/A
N/A
1.353
LoadTest$Stopper
0%
0/7
N/A
1.353
ReadUrler
0%
0/3
N/A
1.353
ReqType
0%
0/8
N/A
1.353
SearchUrler
0%
0/26
0%
0/2
1.353
SectionLevel
0%
0/3
N/A
1.353
Urler
0%
0/1
N/A
1.353
 
 1  
 package org.paneris.bibliomania.loadtest;
 2  
 
 3  
 import java.io.BufferedReader;
 4  
 import java.io.FileInputStream;
 5  
 import java.io.FileReader;
 6  
 import java.io.InputStream;
 7  
 import java.io.ObjectInputStream;
 8  
 import java.net.URL;
 9  
 import java.util.Enumeration;
 10  
 import java.util.Random;
 11  
 import java.util.Vector;
 12  
 
 13  
 import org.melati.util.UnexpectedExceptionException;
 14  
 
 15  0
 class HitStats {
 16  
   public long totalToOpen, totalToFinish;
 17  
   public int successes;
 18  
   public int failures;
 19  
   // public int errors;
 20  
 
 21  
   public void notifyTransaction(long started, long opened, long finished
 22  
                                 // , boolean error
 23  
                                 ) {
 24  0
     totalToOpen += opened - started;
 25  0
     totalToFinish += finished - started;
 26  
     // if (error) ++errors else
 27  0
     ++successes;
 28  0
   }
 29  
 
 30  
   public void notifyFailure() {
 31  0
     ++failures;
 32  0
   }
 33  
 
 34  
   public long meanToOpen() {
 35  0
     return successes == 0 ? 0 : totalToOpen / successes;
 36  
   }
 37  
 
 38  
   public long meanToFinish() {
 39  0
     return successes == 0 ? 0 : totalToFinish / successes;
 40  
   }
 41  
 }
 42  
 
 43  
 class ExponentialDistribution {
 44  
   private double minusMean;
 45  
 
 46  0
   public ExponentialDistribution(double mean) {
 47  0
     minusMean = -mean;
 48  0
   }
 49  
 
 50  
   public double sample() {
 51  
     for (;;) {
 52  0
       float x = LoadTest.random.nextFloat();
 53  0
       if (x != 0.)
 54  0
         return minusMean * Math.log(x);
 55  0
     }
 56  
   }
 57  
 }
 58  
 
 59  
 class BitBucket extends Thread {
 60  
   private String url;
 61  
   private HitStats stats;
 62  
 
 63  0
   public BitBucket(String url, HitStats stats) {
 64  0
     this.url = url;
 65  0
     this.stats = stats;
 66  0
   }
 67  
 
 68  0
   private static final byte[] b = new byte[4096];
 69  
 
 70  
   public void run() {
 71  0
     System.err.println(url);
 72  
     try {
 73  0
       long started = System.currentTimeMillis();
 74  0
       InputStream i = new URL(url).openStream();
 75  0
       long opened = System.currentTimeMillis();
 76  0
       while (i.read(b) != -1);
 77  0
       long finished = System.currentTimeMillis();
 78  
 
 79  0
       stats.notifyTransaction(started, opened, finished);
 80  
     }
 81  0
     catch (Exception e) {
 82  
       //System.err.println(e);
 83  0
       stats.notifyFailure();
 84  0
     }
 85  0
   }
 86  
 }
 87  
 
 88  0
 abstract class Level {
 89  
   abstract String urlFromSection(BookDesc book);
 90  
   String url(BookDesc book) {
 91  0
     return book.sectiongroup + "/" + urlFromSection(book);
 92  
   }
 93  
 }
 94  
 
 95  0
 class SectionLevel extends Level {
 96  
   String urlFromSection(BookDesc book) {
 97  0
     return "" + book.section;
 98  
   }
 99  
 
 100  
   public String toString() {
 101  0
     return "sec";
 102  
   }
 103  
 }
 104  
 
 105  0
 class AuthorLevel extends Level {
 106  
   String urlFromSection(BookDesc book) {
 107  0
     return book.section + "/" + book.author;
 108  
   }
 109  
 
 110  
   public String toString() {
 111  0
     return "aut";
 112  
   }
 113  
 }
 114  
 
 115  0
 class BookLevel extends Level {
 116  
   String urlFromSection(BookDesc book) {
 117  0
     return book.section + "/" + book.author + "/" + book.book;
 118  
   }
 119  
 
 120  
   public String toString() {
 121  0
     return "bok";
 122  
   }
 123  
 }
 124  
 
 125  0
 class ChapterLevel extends Level {
 126  
   String urlFromSection(BookDesc book) {
 127  0
     ChapterDesc c =
 128  
         book.chapters[LoadTest.random.nextInt(book.chapters.length)];
 129  0
     return book.section + "/" + book.author + "/" + book.book + "/" +
 130  
            c.chapter + "/" + (LoadTest.random.nextInt(c.pages) + 1) + ".html";
 131  
   }
 132  
 
 133  
   public String toString() {
 134  0
     return "cha";
 135  
   }
 136  
 }
 137  
 
 138  0
 abstract class Urler {
 139  
   abstract String urlPath(Level level, BookDesc book);
 140  
 }
 141  
 
 142  0
 class ReadUrler extends Urler {
 143  
   String urlPath(Level level, BookDesc book) {
 144  0
     return level.url(book);
 145  
   }
 146  
 
 147  
   public String toString() {
 148  0
     return "read";
 149  
   }
 150  
 }
 151  
 
 152  
 class SearchUrler extends Urler {
 153  
 
 154  
   static String[] words;
 155  
 
 156  
   static {
 157  
     try {
 158  0
       Vector w = new Vector();
 159  0
       BufferedReader r = new BufferedReader(new FileReader("/usr/share/dict/words"));
 160  
       for (;;) {
 161  0
         String s = r.readLine();
 162  0
         if (s == null)
 163  0
           break;
 164  0
         w.addElement(s);
 165  0
       }
 166  0
       words = new String[w.size()];
 167  0
       w.copyInto(words);
 168  
     }
 169  0
     catch (Exception e) {
 170  0
       e.printStackTrace();
 171  0
       System.exit(1);
 172  0
     }
 173  0
   }
 174  
 
 175  
   static String randomWord() {
 176  0
     return words[LoadTest.random.nextInt(words.length)];
 177  
   }
 178  
 
 179  
   int searchgroup;
 180  
   int numwords;
 181  
 
 182  0
   SearchUrler(int searchgroup, int numwords) {
 183  0
     this.searchgroup = searchgroup;
 184  0
     this.numwords = numwords;
 185  0
   }
 186  
 
 187  
   String urlPath(Level level, BookDesc book) {
 188  0
     StringBuffer qt = new StringBuffer();
 189  
 
 190  0
     qt.append(randomWord());
 191  
 
 192  0
     for (int i = 1; i < numwords; ++i) {
 193  0
       qt.append("+");
 194  0
       qt.append(randomWord());
 195  
     }
 196  
 
 197  0
     return
 198  
         "b/org.paneris.bibliomania.Search/" + searchgroup + "/" +
 199  
         level.urlFromSection(book) + "?" + "queryText=" + qt;
 200  
   }
 201  
 
 202  
   public String toString() {
 203  0
     return "search(" + numwords + ")";
 204  
   }
 205  
 }
 206  
 
 207  
 class ReqType {
 208  0
   HitStats stats = new HitStats();
 209  
   Urler urler;
 210  
   Level level;
 211  
 
 212  0
   ReqType(Urler urler, Level level) {
 213  0
     this.urler = urler;
 214  0
     this.level = level;
 215  0
   }
 216  
 
 217  
   void go(BookDesc book) {
 218  0
     new BitBucket(LoadTest.urlPrefix + urler.urlPath(level, book), stats).
 219  
         start();
 220  0
   }
 221  
 
 222  
   public String toString() {
 223  0
     return urler + "/" + level;
 224  
   }
 225  
 }
 226  
 
 227  0
 public class LoadTest {
 228  
 
 229  0
   static Random random = new Random();
 230  
   static String urlPrefix;
 231  
 
 232  
   private long runtimeMillis;
 233  
   private boolean keepGoing;
 234  
   private ExponentialDistribution wait;
 235  0
   private DiscreteDistribution types = new DiscreteDistribution();
 236  
   private int searchsectiongroup;
 237  
 
 238  0
   public LoadTest(long runtimeMillis, int hitsPerSec, int kSearch) {
 239  0
     this.runtimeMillis = runtimeMillis;
 240  0
     wait = new ExponentialDistribution(1000 / hitsPerSec);
 241  
 
 242  0
     types = new DiscreteDistribution();
 243  
 
 244  
     Urler
 245  0
         read = new ReadUrler(),
 246  0
         search1 = new SearchUrler(searchsectiongroup, 1),
 247  0
         search2 = new SearchUrler(searchsectiongroup, 2);
 248  
         //search3 = new SearchUrler(searchsectiongroup, 3);
 249  
 
 250  
     Level
 251  0
         sec = new SectionLevel(),
 252  0
         aut = new AuthorLevel(),
 253  0
         bok = new BookLevel(),
 254  0
         cha = new ChapterLevel();
 255  
     
 256  0
     types.add(new ReqType(read, sec), 6);
 257  0
     types.add(new ReqType(read, aut), 12);
 258  0
     types.add(new ReqType(read, bok), 18);
 259  0
     types.add(new ReqType(read, cha), 37);
 260  
     /*
 261  
     types.add(new ReqType(search1, sec), 2 * kSearch);
 262  
     types.add(new ReqType(search1, aut), 2 * kSearch);
 263  
     types.add(new ReqType(search1, bok), 2 * kSearch);
 264  
     types.add(new ReqType(search2, sec), 1 * kSearch);
 265  
     types.add(new ReqType(search2, aut), 1 * kSearch);
 266  
     types.add(new ReqType(search2, bok), 1 * kSearch);
 267  
     */
 268  0
   }
 269  
 
 270  0
   private class Stopper extends Thread {
 271  
     public void run() {
 272  
       try {
 273  0
         Thread.sleep(runtimeMillis);
 274  
       }
 275  0
       catch (Exception e) {
 276  0
         throw new UnexpectedExceptionException(e);
 277  0
       }
 278  
 
 279  0
       keepGoing = false;
 280  0
     }
 281  
   }
 282  
 
 283  
   public static String pad(String it, int w) {
 284  0
     StringBuffer s = new StringBuffer(w);
 285  0
     while (s.length() + it.length() < w)
 286  0
       s.append(' ');
 287  0
     s.append(it);
 288  0
     return s.toString();
 289  
   }
 290  
 
 291  
   public static String pad(long l, int w) {
 292  0
     return pad("" + l, w);
 293  
   }
 294  
 
 295  
   public void run() throws Exception {
 296  0
     keepGoing = true;
 297  0
     new Stopper().start();
 298  
 
 299  0
     while (keepGoing) {
 300  0
       Thread.sleep((long)wait.sample());
 301  0
       ((ReqType)types.sample()).go((BookDesc)extractTree.books.sample());
 302  
     }
 303  
 
 304  0
     System.err.println("stopping");
 305  0
     Thread.sleep(5);
 306  
 
 307  0
     System.out.println();
 308  0
     System.out.println("        win open end fail");
 309  0
     for (Enumeration h = types.elements(); h.hasMoreElements();) {
 310  0
       ReqType hit = (ReqType)h.nextElement();
 311  0
       System.out.print(hit.toString());
 312  0
       System.out.println(
 313  
           pad(hit.stats.successes, 9) + " " +
 314  
           pad(hit.stats.meanToOpen(), 5) + " " +
 315  
           pad(hit.stats.meanToFinish(), 5) + " " +
 316  
           pad(hit.stats.failures, 5) + " ");
 317  0
     }
 318  0
   }
 319  
 
 320  
   static ExtractTree extractTree;
 321  
 
 322  
   public static void main(String[] args) throws Exception {
 323  0
     ObjectInputStream i =
 324  
         new ObjectInputStream(new FileInputStream("books.ser"));
 325  
 
 326  0
     extractTree = (ExtractTree)i.readObject();
 327  
 
 328  0
     i.close();
 329  
 
 330  
     /*
 331  
     urlPrefix = "http://" + args[0] + "/";
 332  
     new LoadTest(Integer.parseInt(args[1]) * 1000L,
 333  
         Integer.parseInt(args[2]),
 334  
         Integer.parseInt(args[3])).run();
 335  
         */
 336  0
     urlPrefix = "http://bibliomania.com/";
 337  0
     new LoadTest(new Integer(40) * 1000L,
 338  
         new Integer(200),
 339  
         new Integer(32)).run();
 340  0
   }
 341  
 }