package lucandra.benchmarks; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import lucandra.CassandraUtils; import lucandra.IndexReader; import lucandra.IndexWriter; import org.apache.cassandra.thrift.Cassandra; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.Field.Index; import org.apache.lucene.document.Field.Store; import org.apache.lucene.document.Field.TermVector; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TopDocs; import org.apache.lucene.util.Version; import org.apache.thrift.transport.TTransportException; public class BenchmarkTest { private enum Type { read, write, both } private static int numClients = 20; private static int numLoops = 10; private static Type type = Type.both; private static String indexName = "bench"; private static String text = "this is a benchmark of lucandra"; private static String queryString = "text:benchmark"; private static Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT); private static Cassandra.Iface client; private static int threadId = 0; private static final Query query; private static final Document doc; static { try { client = CassandraUtils.createConnection(); query = new QueryParser(Version.LUCENE_CURRENT, "text", analyzer).parse(queryString); doc = new Document(); doc.add(new Field("text", text, Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS)); } catch (TTransportException e) { throw new RuntimeException(e); } catch (ParseException e) { throw new RuntimeException(e); } } private static Runnable getRunnable() { return new Runnable() { private final IndexReader indexReader = new IndexReader(indexName, client); private final IndexWriter indexWriter = new IndexWriter(indexName, client); private final IndexSearcher indexSearcher = new IndexSearcher(indexReader); private final int myThreadId = threadId++; public void run() { switch (type) { case read: read(); break; case write: write(); break; default: both(); } } private void read() { int total = 0; try { for (int i = 0; i < numLoops; i++) { TopDocs td = indexSearcher.search(query, 10); total = td.totalHits; indexReader.reopen(); if (i % 1000 == 999) System.err.println("Thread "+myThreadId+": total "+total); } } catch (IOException e) { throw new RuntimeException(e); } if(myThreadId == 0) System.err.println("Documents found: "+total); } private void write() { for (int i = 0; i < numLoops; i++) { try { indexWriter.addDocument(doc, analyzer); } catch (CorruptIndexException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } } private void both() { int total = 0; for (int i = 0; i < numLoops; i++) { try { if (i % 2 == 1) { TopDocs td = indexSearcher.search(query, 10); total = td.totalHits; indexReader.reopen(); if (i % 1000 == 999) System.err.println("Thread "+myThreadId+": total "+total); } else { indexWriter.addDocument(doc, analyzer); } } catch (CorruptIndexException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } if(myThreadId == 0) System.err.println("Documents found: "+total); } }; } private static void usage() { System.err.print(BenchmarkTest.class.getSimpleName() + " [--clients=<client-count>] [--loop=<loop-count>] [--type=<test-type>]\n" + "\tclients Number of client threads to create: Default is " + numClients + "\n" + "\tloops The number of remote thrift calls each client makes. Default is " + numLoops + "\n" + "\ttype The type of operation to test. Options are:\n" + "\t\tread\n\t\twrite\n\t\tboth (default)\n"); System.exit(0); } public static void main(String[] args) { if(args.length == 0) usage(); // parse args for (int i = 0; i < args.length; i++) { if (args[i].startsWith("--")) { int eq = args[i].indexOf("="); if (eq < 0) usage(); String arg = args[i].substring(2, eq); String value = args[i].substring(eq + 1); try { if (arg.equalsIgnoreCase("clients")) numClients = Integer.valueOf(value); if (arg.equalsIgnoreCase("loops")) numLoops = Integer.valueOf(value); if (arg.equalsIgnoreCase("type")) type = Type.valueOf(value); } catch (Throwable t) { usage(); } } } ExecutorService threadPool = Executors.newFixedThreadPool(numClients); Runnable runners[] = new Runnable[numClients]; for (int i = 0; i < numClients; i++) runners[i] = getRunnable(); System.out.println("Starting Benchmark..."); long startTime = System.currentTimeMillis(); for (int i = 0; i < numClients; i++) threadPool.submit(runners[i]); threadPool.shutdown(); try { threadPool.awaitTermination(1024, TimeUnit.MINUTES); } catch (InterruptedException e) { threadPool.shutdownNow(); System.err.println("Benchmark manually stopped"); System.exit(1); } long endTime = System.currentTimeMillis(); System.out.println("Finished:"); System.out.println("\tclients:"+numClients + ", loops:"+numLoops+ ", type:" + type+ ", rate(ops/sec):" + Math.ceil((double)((numClients * numLoops * 1000)/(endTime - startTime)))); } }