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 <tparker@google.com>
This commit is contained in:
Terry Parker 2018-02-11 13:29:38 -08:00
parent 5efc3dcc6c
commit 302596cc67
3 changed files with 113 additions and 10 deletions

View File

@ -81,6 +81,7 @@
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 PackWriter(final Repository repo, final ObjectReader reader) {
* 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.
* <p>
* 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 PackWriter(final PackConfig config, final ObjectReader reader) {
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);

View File

@ -166,6 +166,36 @@ public long getDeltaBytes() {
* 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<ObjectId> interestingObjects;
@ -270,6 +300,48 @@ public PackStatistics(Accumulator accumulator) {
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.
*

View File

@ -773,6 +773,7 @@ private void service() throws IOException {
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 @@ else if (requestValidator instanceof AnyRequestValidator)
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 @@ else if (requestValidator instanceof AnyRequestValidator)
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 @@ else if (requestValidator instanceof AnyRequestValidator)
}
if (sendPack)
sendPack();
sendPack(accumulator);
}
private static Set<ObjectId> refIdSet(Collection<Ref> refs) {
@ -1093,7 +1100,8 @@ public String getPeerUserAgent() {
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 @@ private boolean negotiate() throws IOException {
} 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 @@ private boolean wantSatisfied(final RevObject want) throws IOException {
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 @@ private void sendPack() throws IOException {
throw err;
}
} else {
sendPack(false);
sendPack(false, accumulator);
}
}
@ -1532,7 +1541,8 @@ private boolean reportInternalServerErrorOverSideband() {
}
@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 @@ private void sendPack(final boolean sideband) throws IOException {
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);