jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r910515 - in /jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi: AbstractJCR2SPITest.java GetItemsTest.java benchmark/ benchmark/ReadPerformanceTest.java
Date Tue, 16 Feb 2010 13:52:44 GMT
Author: mduerig
Date: Tue Feb 16 13:52:44 2010
New Revision: 910515

URL: http://svn.apache.org/viewvc?rev=910515&view=rev
Log:
JCR-2499: Add simple benchmarking tools for jcr2spi read performance

Added:
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/benchmark/
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/benchmark/ReadPerformanceTest.java
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java?rev=910515&r1=910514&r2=910515&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
(original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
Tue Feb 16 13:52:44 2010
@@ -64,6 +64,7 @@
 import org.apache.jackrabbit.spi.RepositoryService;
 import org.apache.jackrabbit.spi.SessionInfo;
 import org.apache.jackrabbit.spi.Subscription;
+import org.apache.jackrabbit.spi.Path.Element;
 import org.apache.jackrabbit.spi.commons.AbstractReadableRepositoryService;
 import org.apache.jackrabbit.spi.commons.ItemInfoBuilder;
 import org.apache.jackrabbit.spi.commons.ItemInfoBuilder.NodeInfoBuilder;
@@ -107,6 +108,30 @@
         repository = getRepository();
     }
 
+    /**
+     * Convert the given <code>path</code> to a JCR path.
+     * @param path
+     * @return
+     */
+    public static final String toJCRPath(Path path) {
+        Element[] elems = path.getElements();
+        StringBuffer jcrPath = new StringBuffer();
+
+        for (int k = 0; k < elems.length; k++) {
+            jcrPath.append(elems[k].getName().getLocalName());
+            if (k + 1 < elems.length || elems.length == 1) {
+                jcrPath.append('/');
+            }
+        }
+
+        return jcrPath.toString();
+    }
+
+    /**
+     * Initialize the mock repository using the <code>builder</code>.
+     * @param builder
+     * @throws RepositoryException
+     */
     protected abstract void initInfosStore(NodeInfoBuilder builder) throws RepositoryException;
 
     protected RepositoryService getRepositoryService() throws RepositoryException, ParseException
{

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java?rev=910515&r1=910514&r2=910515&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java
(original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/GetItemsTest.java
Tue Feb 16 13:52:44 2010
@@ -33,13 +33,11 @@
 import org.apache.jackrabbit.spi.ItemInfo;
 import org.apache.jackrabbit.spi.NodeId;
 import org.apache.jackrabbit.spi.NodeInfo;
-import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.PropertyId;
 import org.apache.jackrabbit.spi.PropertyInfo;
 import org.apache.jackrabbit.spi.QNodeDefinition;
 import org.apache.jackrabbit.spi.RepositoryService;
 import org.apache.jackrabbit.spi.SessionInfo;
-import org.apache.jackrabbit.spi.Path.Element;
 import org.apache.jackrabbit.spi.commons.ItemInfoBuilder.NodeInfoBuilder;
 
 /**
@@ -135,20 +133,6 @@
         }
     }
 
-    private static String toJCRPath(Path path) {
-        Element[] elems = path.getElements();
-        StringBuffer jcrPath = new StringBuffer();
-
-        for (int k = 0; k < elems.length; k++) {
-            jcrPath.append(elems[k].getName().getLocalName());
-            if (k + 1 < elems.length || elems.length == 1) {
-                jcrPath.append('/');
-            }
-        }
-
-        return jcrPath.toString();
-    }
-
     @Override
     protected QNodeDefinition createRootNodeDefinition() {
         fail("Not implemented");

Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/benchmark/ReadPerformanceTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/benchmark/ReadPerformanceTest.java?rev=910515&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/benchmark/ReadPerformanceTest.java
(added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/benchmark/ReadPerformanceTest.java
Tue Feb 16 13:52:44 2010
@@ -0,0 +1,365 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.jcr2spi.benchmark;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.Callable;
+
+import javax.jcr.Item;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.FilterIterator;
+import org.apache.commons.collections.iterators.IteratorChain;
+import org.apache.commons.collections.iterators.SingletonIterator;
+import org.apache.jackrabbit.jcr2spi.AbstractJCR2SPITest;
+import org.apache.jackrabbit.spi.ChildInfo;
+import org.apache.jackrabbit.spi.ItemInfo;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.NodeInfo;
+import org.apache.jackrabbit.spi.PropertyId;
+import org.apache.jackrabbit.spi.PropertyInfo;
+import org.apache.jackrabbit.spi.QNodeDefinition;
+import org.apache.jackrabbit.spi.RepositoryService;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.commons.ItemInfoBuilder.NodeInfoBuilder;
+import org.apache.jackrabbit.spi.commons.ItemInfoBuilder.PropertyInfoBuilder;
+
+/**
+ * Utility for testing jcr2spi read performance
+ */
+public class ReadPerformanceTest extends AbstractJCR2SPITest {
+
+    /**
+     * Depth of the content tree
+     */
+    private static int TREE_DEPTH = 3;
+
+    /**
+     * Number of child nodes of each internal node
+     */
+    private static int NODE_COUNT = 6;
+
+    /**
+     * Number of properties of each node
+     */
+    private static int PROPERTY_COUNT = 60;
+
+    /**
+     * Number of JCR operations to perform per run
+     */
+    private static int OP_COUNT = 500;
+
+    /**
+     * Ratios of the number of items in the whole content tree compared to the number of
items
+     * in a batch of a {@link RepositoryService#getItemInfos(SessionInfo, NodeId)} call.
+     * The array contains one ratio per run
+     */
+    private static int[] BATCH_RATIOS = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
4096, 8192, 16384};
+
+    /**
+     * Valid paths of nodes in the mock repository
+     */
+    private final List<String> nodePaths = new ArrayList<String>();
+
+    /**
+     * Valid paths of properties in the mock repository
+     */
+    private final List<String> propertyPaths = new ArrayList<String>();
+
+    private final Random rnd = new Random(12345);
+
+    /**
+     * This implementation adds a tree of nodes and properties up to certain {@link #TREE_DEPTH}.
+     * Each node has {@link #NODE_COUNT} child nodes and {@link #PROPERTY_COUNT} properties.
+     * {@inheritDoc}
+     */
+    @Override
+    protected void initInfosStore(NodeInfoBuilder builder) throws RepositoryException {
+        addNodes(builder, "");
+    }
+
+    private void addNodes(NodeInfoBuilder builder, String name) throws RepositoryException
{
+        if (name.length() >= TREE_DEPTH) {
+            builder.build();
+            nodePaths.add(toJCRPath(builder.getNodeInfo().getPath()));
+            return;
+        }
+
+        for (int k = 0; k <= NODE_COUNT; k++) {
+            String n = name + k;
+            addNodes(addProperties(builder.createNodeInfo(n), PROPERTY_COUNT), n);
+        }
+        builder.build();
+    }
+
+    private NodeInfoBuilder addProperties(NodeInfoBuilder builder, int count) throws RepositoryException
{
+        for (int k = 0; k < count; k++) {
+            PropertyInfoBuilder pBuilder = builder.createPropertyInfo("property_" + k, "Just
some string value " + k);
+            pBuilder.build();
+            propertyPaths.add(toJCRPath(pBuilder.getPropertyInfo().getPath()));
+        }
+
+        return builder;
+    }
+
+    /**
+     * Create <code>count</number> JCR operations for a <code>session</code>
+     * @param session
+     * @param count
+     * @return
+     */
+    protected Iterable<Callable<Long>> getOperations(final Session session, int
count) {
+        ArrayList<Callable<Long>> callables = new ArrayList<Callable<Long>>();
+        final List<Item> items = new ArrayList<Item>();
+
+        for (int k = 0; k < count; k ++) {
+            switch (rnd.nextInt(4)) {
+                case 0: { // getItem
+                    callables.add(new Callable<Long>() {
+                        public Long call() throws Exception {
+                            int i = rnd.nextInt(nodePaths.size() + propertyPaths.size());
+                            String path = i < nodePaths.size()
+                                ? nodePaths.get(i)
+                                : propertyPaths.get(i - nodePaths.size());
+                            long t1 = System.currentTimeMillis();
+                            Item item = session.getItem(path);
+                            long t2 = System.currentTimeMillis();
+                            items.add(item);
+                            return t2 - t1;
+                        }
+
+                        @Override
+                        public String toString() {
+                            return "getItem";
+                        }
+                    });
+                    break;
+                }
+
+                case 1: { // getNode
+                    callables.add(new Callable<Long>() {
+                        public Long call() throws Exception {
+                            String path = nodePaths.get(rnd.nextInt(nodePaths.size()));
+                            long t1 = System.currentTimeMillis();
+                            Node node = session.getNode(path);
+                            long t2 = System.currentTimeMillis();
+                            items.add(node);
+                            return t2 - t1;
+                        }
+
+                        @Override
+                        public String toString() {
+                            return "getNode";
+                        }
+                    });
+                    break;
+                }
+
+                case 2: { // getProperty
+                    callables.add(new Callable<Long>() {
+                        public Long call() throws Exception {
+                            String path = propertyPaths.get(rnd.nextInt(propertyPaths.size()));
+                            long t1 = System.currentTimeMillis();
+                            Property property = session.getProperty(path);
+                            long t2 = System.currentTimeMillis();
+                            items.add(property);
+                            return t2 - t1;
+                        }
+
+                        @Override
+                        public String toString() {
+                            return "getProperty";
+                        }
+                    });
+                    break;
+                }
+
+                case 3: { // refresh
+                    callables.add(new Callable<Long>() {
+                        public Long call() throws Exception {
+                            if (items.isEmpty()) {
+                                return 0L;
+                            }
+                            Item item = items.get(rnd.nextInt(items.size()));
+                            long t1 = System.currentTimeMillis();
+                            item.refresh(rnd.nextBoolean());
+                            long t2 = System.currentTimeMillis();
+                            return t2 - t1;
+                        }
+
+                        @Override
+                        public String toString() {
+                            return "refresh";
+                        }
+                    });
+                    break;
+                }
+
+                default:
+                    fail("Invalid case in switch");
+            }
+        }
+
+        return callables;
+    }
+
+    private int roundTripCount;
+    private int batchRatio;
+
+    /**
+     * Perform {@link #OP_COUNT} JCR operations on a fresh session once for each batch ratio
value
+     * given in {@link #BATCH_RATIOS}.
+     * @throws Exception
+     */
+    public void testReadOperations() throws Exception {
+        for (int ratio : BATCH_RATIOS) {
+            testReadOperations(OP_COUNT, ratio);
+        }
+    }
+
+    private void testReadOperations(int opCount, int batchRatio) throws Exception {
+        this.batchRatio = batchRatio;
+        this.roundTripCount = 0;
+
+        Map<String, Integer> opCounts = new HashMap<String, Integer>();
+        Map<String, Long> opTimes = new HashMap<String, Long>();
+        Session session = repository.login();
+
+        Iterable<Callable<Long>> operations = getOperations(session, opCount);
+        for (Callable<Long> operation : operations) {
+            String opName = operation.toString();
+            Long t = operation.call();
+
+            if (opCounts.containsKey(opName)) {
+                opCounts.put(opName, opCounts.get(opName) + 1);
+                opTimes.put(opName, opTimes.get(opName) + t);
+            }
+            else {
+                opCounts.put(opName, 1);
+                opTimes.put(opName, t);
+            }
+        }
+
+        System.out.println("Batch ratio: " + batchRatio);
+        System.out.println("Round trips: " + roundTripCount);
+
+        int count = 0;
+        long time = 0L;
+        for (String opName : opCounts.keySet()) {
+            int c = opCounts.get(opName);
+            count += c;
+            System.out.println(opName + " count: " + c);
+
+            long t = opTimes.get(opName);
+            time += t;
+            System.out.println(opName + " time: " + t);
+        }
+
+        System.out.println("Total count: " + count);
+        System.out.println("Total time: " + time);
+
+        session.logout();
+    }
+
+    private Iterator<ItemInfo> getBatch() {
+        return filter(itemInfoStore.getItemInfos(), new Predicate<ItemInfo>() {
+            public boolean evaluate(ItemInfo value) {
+                return rnd.nextInt(batchRatio) == 0;
+            }
+        });
+    }
+
+    // -----------------------------------------------------< RepositoryService >---
+
+    @Override
+    protected QNodeDefinition createRootNodeDefinition() {
+        fail("not implemented: createRootNodeDefinition");
+        return null;
+    }
+
+    @Override
+    public Iterator<? extends ItemInfo> getItemInfos(SessionInfo sessionInfo, NodeId
nodeId)
+            throws ItemNotFoundException, RepositoryException {
+
+        roundTripCount++;
+        NodeInfo nodeInfo = itemInfoStore.getNodeInfo(nodeId);
+        return chain(singleton(nodeInfo), getBatch());
+    }
+
+    @Override
+    public NodeInfo getNodeInfo(SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException
{
+        roundTripCount++;
+        return itemInfoStore.getNodeInfo(nodeId);
+    }
+
+    @Override
+    public PropertyInfo getPropertyInfo(SessionInfo sessionInfo, PropertyId propertyId)
+            throws ItemNotFoundException {
+
+        roundTripCount++;
+        return itemInfoStore.getPropertyInfo(propertyId);
+    }
+
+    @Override
+    public Iterator<ChildInfo> getChildInfos(SessionInfo sessionInfo, NodeId parentId)
+            throws ItemNotFoundException, RepositoryException {
+
+        roundTripCount++;
+        return itemInfoStore.getChildInfos(parentId);
+    }
+
+    // -----------------------------------------------------< private >---
+
+    private interface Predicate<T> {
+        public boolean evaluate(T value);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Iterator<T> chain(Iterator<? extends T> first, Iterator<?
extends T> second) {
+        return new IteratorChain(first, second);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Iterator<T> singleton(T value) {
+        return new SingletonIterator(value);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Iterator<T> empty() {
+        return EmptyIterator.INSTANCE;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Iterator<T> filter(Iterator<T> source, final Predicate<T>
predicate) {
+        return new FilterIterator(source, new org.apache.commons.collections.Predicate()
{
+            public boolean evaluate(Object object) {
+                return predicate.evaluate((T) object);
+            }
+        });
+    }
+
+}

Propchange: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/benchmark/ReadPerformanceTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message