From 36f05a9c27e6961b10df0b65014ffc869f4f8686 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 22 Jan 2010 18:42:12 -0800 Subject: [PATCH] Optimize RefAdvertiser performance by avoiding sorting Don't copy and sort the set of references if they are passed through in a RefMap or a SortedMap using the key's natural sort ordering. Either map is already in the order we want to present the items to the client in, so copying and sorting is a waste of local CPU and memory. Change-Id: I49ada7c1220e0fc2a163b9752c2b77525d9c82c1 Signed-off-by: Shawn O. Pearce --- .../jgit/http/server/InfoRefsServlet.java | 2 +- .../eclipse/jgit/transport/ReceivePack.java | 2 +- .../eclipse/jgit/transport/RefAdvertiser.java | 23 +++++++++++++------ .../eclipse/jgit/transport/UploadPack.java | 4 ++-- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java index 3b615198a..b766196fd 100644 --- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/InfoRefsServlet.java @@ -99,7 +99,7 @@ protected void end() { Map refs = db.getAllRefs(); refs.remove(Constants.HEAD); - adv.send(refs.values()); + adv.send(refs); return out.toString().getBytes(Constants.CHARACTER_ENCODING); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java index f8be827df..15bdf9618 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -591,7 +591,7 @@ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException { adv.advertiseCapability(CAPABILITY_OFS_DELTA); refs = db.getAllRefs(); final Ref head = refs.remove(Constants.HEAD); - adv.send(refs.values()); + adv.send(refs); if (!head.isSymbolic()) adv.advertiseHave(head.getObjectId()); adv.includeAdditionalHaves(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java index 77f30140c..694a2e0f1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java @@ -44,9 +44,10 @@ package org.eclipse.jgit.transport; import java.io.IOException; -import java.util.Collection; import java.util.LinkedHashSet; +import java.util.Map; import java.util.Set; +import java.util.SortedMap; import org.eclipse.jgit.lib.AlternateRepositoryDatabase; import org.eclipse.jgit.lib.AnyObjectId; @@ -59,6 +60,7 @@ import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.util.RefMap; /** Support for the start of {@link UploadPack} and {@link ReceivePack}. */ public abstract class RefAdvertiser { @@ -122,7 +124,7 @@ public void init(final RevWalk protoWalk, final RevFlag advertisedFlag) { *

* This method must be invoked prior to any of the following: *

    - *
  • {@link #send(Collection)} + *
  • {@link #send(Map)} *
  • {@link #advertiseHave(AnyObjectId)} *
  • {@link #includeAdditionalHaves()} *
@@ -140,7 +142,7 @@ public void setDerefTags(final boolean deref) { *

* This method must be invoked prior to any of the following: *

    - *
  • {@link #send(Collection)} + *
  • {@link #send(Map)} *
  • {@link #advertiseHave(AnyObjectId)} *
  • {@link #includeAdditionalHaves()} *
@@ -160,14 +162,14 @@ public void advertiseCapability(String name) { * * @param refs * zero or more refs to format for the client. The collection is - * copied and sorted before display and therefore may appear in - * any order. + * sorted before display if necessary, and therefore may appear + * in any order. * @throws IOException * the underlying output stream failed to write out an * advertisement record. */ - public void send(final Collection refs) throws IOException { - for (final Ref r : RefComparator.sort(refs)) { + public void send(final Map refs) throws IOException { + for (final Ref r : getSortedRefs(refs)) { final RevObject obj = parseAnyOrNull(r.getObjectId()); if (obj != null) { advertiseAny(obj, r.getName()); @@ -177,6 +179,13 @@ public void send(final Collection refs) throws IOException { } } + private Iterable getSortedRefs(Map all) { + if (all instanceof RefMap + || (all instanceof SortedMap && ((SortedMap) all).comparator() == null)) + return all.values(); + return RefComparator.sort(all.values()); + } + /** * Advertise one object is available using the magic {@code .have}. *

diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java index 6b81bc492..57bb2adbf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009, Google Inc. + * Copyright (C) 2008-2010, Google Inc. * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -330,7 +330,7 @@ public void sendAdvertisedRefs(final RefAdvertiser adv) throws IOException { adv.advertiseCapability(OPTION_NO_PROGRESS); adv.setDerefTags(true); refs = db.getAllRefs(); - adv.send(refs.values()); + adv.send(refs); adv.end(); }