Browse Source

PackWriter: Collect stats by object type

Frequently enough I'm wondering how much of a pack is commits vs.
trees, and the total line doesn't really tell us this because its
a gross total from the pack. Computing the counts per object type
is simple during packing, as PackWriter already has everything in
memory broken up by object type.  Its virtually free to get these
values and track them.

Change-Id: Id5e6b1902ea909c72f103a0fbca5d8bc316f9ab3
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
stable-0.12
Shawn O. Pearce 14 years ago
parent
commit
bb1956e647
  1. 128
      org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java

128
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java

@ -168,6 +168,8 @@ public class PackWriter {
private final Statistics stats; private final Statistics stats;
private Statistics.ObjectType typeStats;
private List<ObjectToPack> sortedByName; private List<ObjectToPack> sortedByName;
private byte packcsum[]; private byte packcsum[];
@ -650,14 +652,17 @@ public class PackWriter {
writeMonitor.beginTask(JGitText.get().writingObjects, (int) objCnt); writeMonitor.beginTask(JGitText.get().writingObjects, (int) objCnt);
long writeStart = System.currentTimeMillis(); long writeStart = System.currentTimeMillis();
long headerStart = out.length();
out.writeFileHeader(PACK_VERSION_GENERATED, objCnt); out.writeFileHeader(PACK_VERSION_GENERATED, objCnt);
out.flush(); out.flush();
long headerEnd = out.length();
writeObjects(out); writeObjects(out);
if (!edgeObjects.isEmpty() || !cachedPacks.isEmpty()) if (!edgeObjects.isEmpty() || !cachedPacks.isEmpty()) {
stats.thinPackBytes = out.length() - (headerEnd - headerStart); for (Statistics.ObjectType typeStat : stats.objectTypes) {
if (typeStat == null)
continue;
stats.thinPackBytes += typeStat.bytes;
}
}
for (CachedPack pack : cachedPacks) { for (CachedPack pack : cachedPacks) {
long deltaCnt = pack.getDeltaCount(); long deltaCnt = pack.getDeltaCount();
@ -672,6 +677,16 @@ public class PackWriter {
stats.totalBytes = out.length(); stats.totalBytes = out.length();
stats.reusedPacks = Collections.unmodifiableList(cachedPacks); stats.reusedPacks = Collections.unmodifiableList(cachedPacks);
for (Statistics.ObjectType typeStat : stats.objectTypes) {
if (typeStat == null)
continue;
typeStat.cntDeltas += typeStat.reusedDeltas;
stats.reusedObjects += typeStat.reusedObjects;
stats.reusedDeltas += typeStat.reusedDeltas;
stats.totalDeltas += typeStat.cntDeltas;
}
reader.release(); reader.release();
writeMonitor.endTask(); writeMonitor.endTask();
} }
@ -1015,12 +1030,21 @@ public class PackWriter {
private void writeObjects(PackOutputStream out, List<ObjectToPack> list) private void writeObjects(PackOutputStream out, List<ObjectToPack> list)
throws IOException { throws IOException {
if (list.isEmpty())
return;
typeStats = stats.objectTypes[list.get(0).getType()];
long beginOffset = out.length();
if (reuseSupport != null) { if (reuseSupport != null) {
reuseSupport.writeObjects(out, list); reuseSupport.writeObjects(out, list);
} else { } else {
for (ObjectToPack otp : list) for (ObjectToPack otp : list)
out.writeObject(otp); out.writeObject(otp);
} }
typeStats.bytes += out.length() - beginOffset;
typeStats.cntObjects = list.size();
} }
void writeObject(PackOutputStream out, ObjectToPack otp) throws IOException { void writeObject(PackOutputStream out, ObjectToPack otp) throws IOException {
@ -1039,10 +1063,10 @@ public class PackWriter {
reuseSupport.copyObjectAsIs(out, otp, reuseValidate); reuseSupport.copyObjectAsIs(out, otp, reuseValidate);
out.endObject(); out.endObject();
otp.setCRC(out.getCRC32()); otp.setCRC(out.getCRC32());
stats.reusedObjects++; typeStats.reusedObjects++;
if (otp.isDeltaRepresentation()) { if (otp.isDeltaRepresentation()) {
stats.totalDeltas++; typeStats.reusedDeltas++;
stats.reusedDeltas++; typeStats.deltaBytes += out.length() - otp.getOffset();
} }
return; return;
} catch (StoredObjectRepresentationNotAvailableException gone) { } catch (StoredObjectRepresentationNotAvailableException gone) {
@ -1138,7 +1162,8 @@ public class PackWriter {
DeflaterOutputStream dst = new DeflaterOutputStream(out, deflater); DeflaterOutputStream dst = new DeflaterOutputStream(out, deflater);
delta.writeTo(dst, null); delta.writeTo(dst, null);
dst.finish(); dst.finish();
stats.totalDeltas++; typeStats.cntDeltas++;
typeStats.deltaBytes += out.length() - otp.getOffset();
} }
private TemporaryBuffer.Heap delta(final ObjectToPack otp) private TemporaryBuffer.Heap delta(final ObjectToPack otp)
@ -1579,6 +1604,74 @@ public class PackWriter {
/** Summary of how PackWriter created the pack. */ /** Summary of how PackWriter created the pack. */
public static class Statistics { public static class Statistics {
/** Statistics about a single class of object. */
public static class ObjectType {
long cntObjects;
long cntDeltas;
long reusedObjects;
long reusedDeltas;
long bytes;
long deltaBytes;
/**
* @return total number of objects output. This total includes the
* value of {@link #getDeltas()}.
*/
public long getObjects() {
return cntObjects;
}
/**
* @return total number of deltas output. This may be lower than the
* actual number of deltas if a cached pack was reused.
*/
public long getDeltas() {
return cntDeltas;
}
/**
* @return number of objects whose existing representation was
* reused in the output. This count includes
* {@link #getReusedDeltas()}.
*/
public long getReusedObjects() {
return reusedObjects;
}
/**
* @return number of deltas whose existing representation was reused
* in the output, as their base object was also output or
* was assumed present for a thin pack. This may be lower
* than the actual number of reused deltas if a cached pack
* was reused.
*/
public long getReusedDeltas() {
return reusedDeltas;
}
/**
* @return total number of bytes written. This size includes the
* object headers as well as the compressed data. This size
* also includes all of {@link #getDeltaBytes()}.
*/
public long getBytes() {
return bytes;
}
/**
* @return number of delta bytes written. This size includes the
* object headers for the delta objects.
*/
public long getDeltaBytes() {
return deltaBytes;
}
}
Set<ObjectId> interestingObjects; Set<ObjectId> interestingObjects;
Set<ObjectId> uninterestingObjects; Set<ObjectId> uninterestingObjects;
@ -1611,6 +1704,16 @@ public class PackWriter {
long timeWriting; long timeWriting;
ObjectType[] objectTypes;
{
objectTypes = new ObjectType[5];
objectTypes[Constants.OBJ_COMMIT] = new ObjectType();
objectTypes[Constants.OBJ_TREE] = new ObjectType();
objectTypes[Constants.OBJ_BLOB] = new ObjectType();
objectTypes[Constants.OBJ_TAG] = new ObjectType();
}
/** /**
* @return unmodifiable collection of objects to be included in the * @return unmodifiable collection of objects to be included in the
* pack. May be null if the pack was hand-crafted in a unit * pack. May be null if the pack was hand-crafted in a unit
@ -1708,6 +1811,15 @@ public class PackWriter {
return thinPackBytes; return thinPackBytes;
} }
/**
* @param typeCode
* object type code, e.g. OBJ_COMMIT or OBJ_TREE.
* @return information about this type of object in the pack.
*/
public ObjectType byObjectType(int typeCode) {
return objectTypes[typeCode];
}
/** /**
* @return time in milliseconds spent enumerating the objects that need * @return time in milliseconds spent enumerating the objects that need
* to be included in the output. This time includes any restarts * to be included in the output. This time includes any restarts

Loading…
Cancel
Save