From 302596cc675d00e41f0ff07efef58063afe20c79 Mon Sep 17 00:00:00 2001 From: Terry Parker Date: Sun, 11 Feb 2018 13:29:38 -0800 Subject: [PATCH] Add negotiation statistics to PackStatistics Add fetch statistics for the counts of advertised refs, wants and haves. Also add the duration in milliseconds for the negotiation phase. For non-bidirectional transports like HTTP, this is the time for the final round that sends the pack back to the user. Change-Id: I1af7ffd3cb7b62182340682e2a243691ea24ec2e Signed-off-by: Terry Parker --- .../internal/storage/pack/PackWriter.java | 22 +++++- .../jgit/storage/pack/PackStatistics.java | 72 +++++++++++++++++++ .../eclipse/jgit/transport/UploadPack.java | 29 +++++--- 3 files changed, 113 insertions(+), 10 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index 71d10ac45..42df1a658 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -81,6 +81,7 @@ import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.LargeObjectException; @@ -355,6 +356,24 @@ public class PackWriter implements AutoCloseable { * reader to read from the repository with. */ public PackWriter(final PackConfig config, final ObjectReader reader) { + this(config, reader, null); + } + + /** + * Create writer with a specified configuration. + *

+ * Objects for packing are specified in {@link #preparePack(Iterator)} or + * {@link #preparePack(ProgressMonitor, Set, Set)}. + * + * @param config + * configuration for the pack writer. + * @param reader + * reader to read from the repository with. + * @param statsAccumulator + * accumulator for statics + */ + public PackWriter(PackConfig config, final ObjectReader reader, + @Nullable PackStatistics.Accumulator statsAccumulator) { this.config = config; this.reader = reader; if (reader instanceof ObjectReuseAsIs) @@ -365,7 +384,8 @@ public class PackWriter implements AutoCloseable { deltaBaseAsOffset = config.isDeltaBaseAsOffset(); reuseDeltas = config.isReuseDeltas(); reuseValidate = true; // be paranoid by default - stats = new PackStatistics.Accumulator(); + stats = statsAccumulator != null ? statsAccumulator + : new PackStatistics.Accumulator(); state = new MutableState(); selfRef = new WeakReference<>(this); instances.put(selfRef, Boolean.TRUE); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java index 68cffd5b3..68878e5a6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java @@ -166,6 +166,36 @@ public class PackStatistics { * POJO for accumulating the statistics. */ public static class Accumulator { + /** + * The count of references in the ref advertisement. + * + * @since 4.11 + */ + public long advertised; + + /** + * The count of client wants. + * + * @since 4.11 + */ + public long wants; + + /** + * The count of client haves. + * + * @since 4.11 + */ + public long haves; + + /** + * Time in ms spent in the negotiation phase. For non-bidirectional + * transports (e.g., HTTP), this is only for the final request that + * sends back the pack file. + * + * @since 4.11 + */ + public long timeNegotiating; + /** The set of objects to be included in the pack. */ public Set interestingObjects; @@ -270,6 +300,48 @@ public class PackStatistics { statistics = accumulator; } + /** + * Get the count of references in the ref advertisement. + * + * @return count of refs in the ref advertisement. + * @since 4.11 + */ + public long getAdvertised() { + return statistics.advertised; + } + + /** + * Get the count of client wants. + * + * @return count of client wants. + * @since 4.11 + */ + public long getWants() { + return statistics.wants; + } + + /** + * Get the count of client haves. + * + * @return count of client haves. + * @since 4.11 + */ + public long getHaves() { + return statistics.haves; + } + + /** + * Time in ms spent in the negotiation phase. For non-bidirectional + * transports (e.g., HTTP), this is only for the final request that sends + * back the pack file. + * + * @return time for ref advertisement in ms. + * @since 4.11 + */ + public long getTimeNegotiating() { + return statistics.timeNegotiating; + } + /** * Get unmodifiable collection of objects to be included in the pack. * 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 5034c34d8..0209be1f7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -773,6 +773,7 @@ public class UploadPack { boolean sendPack = false; // If it's a non-bidi request, we need to read the entire request before // writing a response. Buffer the response until then. + PackStatistics.Accumulator accumulator = new PackStatistics.Accumulator(); try { if (biDirectionalPipe) sendAdvertisedRefs(new PacketLineOutRefAdvertiser(pckOut)); @@ -781,12 +782,15 @@ public class UploadPack { else advertised = refIdSet(getAdvertisedOrDefaultRefs().values()); + long negotiateStart = System.currentTimeMillis(); + accumulator.advertised = advertised.size(); recvWants(); if (wantIds.isEmpty()) { preUploadHook.onBeginNegotiateRound(this, wantIds, 0); preUploadHook.onEndNegotiateRound(this, wantIds, 0, 0, false); return; } + accumulator.wants = wantIds.size(); if (options.contains(OPTION_MULTI_ACK_DETAILED)) { multiAck = MultiAck.DETAILED; @@ -802,7 +806,10 @@ public class UploadPack { processShallow(); if (!clientShallowCommits.isEmpty()) walk.assumeShallow(clientShallowCommits); - sendPack = negotiate(); + sendPack = negotiate(accumulator); + accumulator.timeNegotiating += System.currentTimeMillis() + - negotiateStart; + if (sendPack && !biDirectionalPipe) { // Ensure the request was fully consumed. Any remaining input must // be a protocol error. If we aren't at EOF the implementation is broken. @@ -849,7 +856,7 @@ public class UploadPack { } if (sendPack) - sendPack(); + sendPack(accumulator); } private static Set refIdSet(Collection refs) { @@ -1093,7 +1100,8 @@ public class UploadPack { return UserAgent.getAgent(options, userAgent); } - private boolean negotiate() throws IOException { + private boolean negotiate(PackStatistics.Accumulator accumulator) + throws IOException { okToGiveUp = Boolean.FALSE; ObjectId last = ObjectId.zeroId(); @@ -1127,7 +1135,7 @@ public class UploadPack { } else if (line.startsWith("have ") && line.length() == 45) { //$NON-NLS-1$ peerHas.add(ObjectId.fromString(line.substring(5))); - + accumulator.haves++; } else if (line.equals("done")) { //$NON-NLS-1$ last = processHaveLines(peerHas, last); @@ -1485,12 +1493,13 @@ public class UploadPack { return false; } - private void sendPack() throws IOException { + private void sendPack(PackStatistics.Accumulator accumulator) + throws IOException { final boolean sideband = options.contains(OPTION_SIDE_BAND) || options.contains(OPTION_SIDE_BAND_64K); if (sideband) { try { - sendPack(true); + sendPack(true, accumulator); } catch (ServiceMayNotContinueException noPack) { // This was already reported on (below). throw noPack; @@ -1511,7 +1520,7 @@ public class UploadPack { throw err; } } else { - sendPack(false); + sendPack(false, accumulator); } } @@ -1532,7 +1541,8 @@ public class UploadPack { } @SuppressWarnings("deprecation") - private void sendPack(final boolean sideband) throws IOException { + private void sendPack(final boolean sideband, + PackStatistics.Accumulator accumulator) throws IOException { ProgressMonitor pm = NullProgressMonitor.INSTANCE; OutputStream packOut = rawOut; @@ -1573,7 +1583,8 @@ public class UploadPack { PackConfig cfg = packConfig; if (cfg == null) cfg = new PackConfig(db); - final PackWriter pw = new PackWriter(cfg, walk.getObjectReader()); + final PackWriter pw = new PackWriter(cfg, walk.getObjectReader(), + accumulator); try { pw.setIndexDisabled(true); pw.setUseCachedPacks(true);