Julian Reschke wrote:
At the end of the day, what we should do is *measure* the performance of JCR2SPI compared to native implementations. I'll try to submit a few tests soon.
...

OK, I've got tests (not polished) and numbers.

Scenario:

A collection /a/b with 500 members, each 1024 in size, content type application/octet-stream.

Test code that obtains all members, checking content type, size, and total number.

My store can do that in ~80ms.

Why doing it through SPI (with limited batch read support), it will take ~1500ms.

Wrapping that with JCR2SPI, it takes around ~2700ms.

So it seems we need drastically remove the overhead introduced by the SPI API.

Test code below:


private String createTestCollJcr(String p_parentpath, int p_members, int p_size) throws Exception {
    Repository l_repository = getRepository();
    Session l_session = null;

    try {
      l_session = l_repository.login(getCredentials());

      Node l_folder = null;
      try {
        l_folder = (Node)l_session.getItem(p_parentpath + "/bigcoll");
      }
      catch (RepositoryException ex) {
        // nothing to do
      }

      // delete when needed
      if (l_folder != null) {
        l_folder.remove();
        l_session.save();
      }

      Node l_parent = (Node)l_session.getItem(p_parentpath);
      l_folder = l_parent.addNode("bigcoll", "nt:folder");
      assertNotNull(l_folder);

      long l_cnt = 0;

      while (l_cnt < p_members) {
InputStream l_is = new BufferedInputStream(new ContentGenerator(p_size), p_size);
        Node l_new = l_folder.addNode("tst" + l_cnt, "nt:file");
        Node l_cnew = l_new.addNode("jcr:content", "nt:resource");
        l_cnew.setProperty("jcr:data", l_is);
        l_cnew.setProperty("jcr:mimeType", "application/octet-stream");
        l_session.save();
        l_cnt += 1;
      }
    }
    finally {
      if (l_session != null) {
        l_session.logout();
      }
    }

    return p_parentpath + "/bigcoll";
  }


  private static int BIGCOLLMEMBERS = 500;
  private static int BIGCOLLMEMBERSIZE = 1024;
  private static String BIGCOLLMIMETYPE = "application/octet-stream";

  public void testGetMembersSpi() throws Exception {

String l_path = createTestColl(this.m_path, BIGCOLLMEMBERS, BIGCOLLMEMBERSIZE);

    RepositoryService l_rs = getRepositoryService();
    SessionInfo l_si = null;

    try {
      l_si = l_rs.obtain(getCredentials(), null);

      long l_start = System.currentTimeMillis();
      long l_cnt = 0;

      while (System.currentTimeMillis() - l_start < MS || l_cnt < 5) {
        NodeId l_nid = TestPerf.computeNodeId(l_rs, l_si, l_path);
        int l_members = 0;
for (Iterator<ChildInfo> l_it = (Iterator<ChildInfo>)l_rs.getChildInfos(l_si, l_nid); l_it.hasNext(); ) {
          ChildInfo l_c = l_it.next();
          assertNotNull(l_c);
NodeId l_cnid = l_rs.getIdFactory().createNodeId(l_c.getUniqueID());
          NodeInfo l_node = null;
          NodeInfo l_contentnode = null;
          PropertyInfo l_mimetype = null;
          PropertyInfo l_data = null;
          Iterator l_iteminfos = l_rs.getItemInfos(l_si, l_cnid);
          l_node = (NodeInfo)l_iteminfos.next();
          assertNotNull(l_node);

          while (l_iteminfos.hasNext()) {
            ItemInfo l_i = (ItemInfo)l_iteminfos.next();
if (l_i.getParentId().equals(l_node.getId()) && NameConstants.JCR_CONTENT.equals(l_i.getName())) {
              l_contentnode = (NodeInfo)l_i;
            }
if (l_contentnode != null && l_i.getParentId().equals(l_contentnode.getId()) && NameConstants.JCR_MIMETYPE.equals(l_i.getName())) {
              l_mimetype = (PropertyInfo)l_i;
            }
if (l_contentnode != null && l_i.getParentId().equals(l_contentnode.getId()) && NameConstants.JCR_DATA.equals(l_i.getName())) {
              l_data = (PropertyInfo)l_i;
            }
          }

          if (l_contentnode == null) {
// explicitly fetch the content node, it wasn't returned with the parent NodeId l_contentnodeid = l_rs.getIdFactory().createNodeId(l_c.getUniqueID(), l_rs.getPathFactory().create(NameConstants.JCR_CONTENT)); Iterator l_iteminfos2 = l_rs.getItemInfos(l_si, l_contentnodeid);
            l_contentnode = (NodeInfo)l_iteminfos2.next();
            while (l_iteminfos2.hasNext()) {
              ItemInfo l_i = (ItemInfo)l_iteminfos2.next();
if (l_i.getParentId().equals(l_contentnode.getId()) && NameConstants.JCR_MIMETYPE.equals(l_i.getName())) {
                l_mimetype = (PropertyInfo)l_i;
              }
if (l_i.getParentId().equals(l_contentnode.getId()) && NameConstants.JCR_DATA.equals(l_i.getName())) {
                l_data = (PropertyInfo)l_i;
              }
            }
          }

          assertNotNull(l_contentnode);

          if (l_mimetype == null) {
// explicitly fetch the mime type property, it wasn't returned with the parent PropertyId l_mimetypeid = l_rs.getIdFactory().createPropertyId(l_contentnode.getId(), NameConstants.JCR_MIMETYPE);
            l_mimetype = l_rs.getPropertyInfo(l_si, l_mimetypeid);
          }

          assertNotNull(l_mimetype);
assertEquals(BIGCOLLMIMETYPE, l_mimetype.getValues()[0].getString());

          if (l_data == null) {
// explicitly fetch the mime type property, it wasn't returned with the parent PropertyId l_dataid = l_rs.getIdFactory().createPropertyId(l_contentnode.getId(), NameConstants.JCR_DATA);
            l_data = l_rs.getPropertyInfo(l_si, l_dataid);
          }

          assertNotNull(l_data);
assertEquals(BIGCOLLMEMBERSIZE, l_data.getValues()[0].getLength());

          l_members += 1;
        }
        assertEquals(BIGCOLLMEMBERS, l_members);
        l_cnt += 1;
      }

      long l_elapsed = System.currentTimeMillis() - l_start;

LOG.info(String.format("GetMembers - SPI: %.4fms per call (%d iterations)", (double)l_elapsed / l_cnt, l_cnt));

    }
    finally {
      if (l_si != null) {
        l_rs.dispose(l_si);
      }
    }
  }

  public void testGetMembersJcr() throws Exception {

String l_path = createTestCollJcr(this.m_path, BIGCOLLMEMBERS, BIGCOLLMEMBERSIZE);

    Repository l_repository = getRepository();
    Session l_session = null;

    try {
      l_session = l_repository.login(getCredentials(), null);

      long l_start = System.currentTimeMillis();
      long l_cnt = 0;

      while (System.currentTimeMillis() - l_start < MS || l_cnt < 5) {
        Node l_dir = (Node)l_session.getItem(l_path);
        assertNotNull(l_dir);
        int l_members = 0;
        for (NodeIterator l_it = l_dir.getNodes(); l_it.hasNext(); ) {
          Node l_c = l_it.nextNode();
          Node l_e = l_c.getNode("jcr:content");
          String l_type = l_e.getProperty("jcr:mimeType").getString();
          long l_length = l_e.getProperty("jcr:data").getLength();
          assertTrue(l_c.isNode());
          assertEquals(BIGCOLLMIMETYPE, l_type);
          assertEquals(BIGCOLLMEMBERSIZE, l_length);
          l_members += 1;
        }
        assertEquals(BIGCOLLMEMBERS, l_members);
        l_session.refresh(false);
        l_cnt += 1;
      }

      long l_elapsed = System.currentTimeMillis() - l_start;

LOG.info(String.format("GetMembers - JCR: %.4fms per call (%d iterations)", (double)l_elapsed / l_cnt, l_cnt));

    }
    finally {
      if (l_session != null) {
        l_session.logout();
      }
    }
  }

  private class ContentGenerator extends InputStream {

    private long m_length;
    private long m_position;

    public ContentGenerator(long p_length) {
      this.m_length = p_length;
      this.m_position = 0;
    }

    public int read() {

      if (this.m_position++ < this.m_length) {
        return 0;
      }
      else {
        return -1;
      }
    }
  }

Reply via email to