private final Statistics stats;
+ private Statistics.ObjectType typeStats;
+
private List<ObjectToPack> sortedByName;
private byte packcsum[];
writeMonitor.beginTask(JGitText.get().writingObjects, (int) objCnt);
long writeStart = System.currentTimeMillis();
- long headerStart = out.length();
out.writeFileHeader(PACK_VERSION_GENERATED, objCnt);
out.flush();
- long headerEnd = out.length();
writeObjects(out);
- if (!edgeObjects.isEmpty() || !cachedPacks.isEmpty())
- stats.thinPackBytes = out.length() - (headerEnd - headerStart);
+ if (!edgeObjects.isEmpty() || !cachedPacks.isEmpty()) {
+ for (Statistics.ObjectType typeStat : stats.objectTypes) {
+ if (typeStat == null)
+ continue;
+ stats.thinPackBytes += typeStat.bytes;
+ }
+ }
for (CachedPack pack : cachedPacks) {
long deltaCnt = pack.getDeltaCount();
stats.totalBytes = out.length();
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();
writeMonitor.endTask();
}
private void writeObjects(PackOutputStream out, List<ObjectToPack> list)
throws IOException {
+ if (list.isEmpty())
+ return;
+
+ typeStats = stats.objectTypes[list.get(0).getType()];
+ long beginOffset = out.length();
+
if (reuseSupport != null) {
reuseSupport.writeObjects(out, list);
} else {
for (ObjectToPack otp : list)
out.writeObject(otp);
}
+
+ typeStats.bytes += out.length() - beginOffset;
+ typeStats.cntObjects = list.size();
}
void writeObject(PackOutputStream out, ObjectToPack otp) throws IOException {
reuseSupport.copyObjectAsIs(out, otp, reuseValidate);
out.endObject();
otp.setCRC(out.getCRC32());
- stats.reusedObjects++;
+ typeStats.reusedObjects++;
if (otp.isDeltaRepresentation()) {
- stats.totalDeltas++;
- stats.reusedDeltas++;
+ typeStats.reusedDeltas++;
+ typeStats.deltaBytes += out.length() - otp.getOffset();
}
return;
} catch (StoredObjectRepresentationNotAvailableException gone) {
DeflaterOutputStream dst = new DeflaterOutputStream(out, deflater);
delta.writeTo(dst, null);
dst.finish();
- stats.totalDeltas++;
+ typeStats.cntDeltas++;
+ typeStats.deltaBytes += out.length() - otp.getOffset();
}
private TemporaryBuffer.Heap delta(final ObjectToPack otp)
/** Summary of how PackWriter created the pack. */
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> uninterestingObjects;
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
* pack. May be null if the pack was hand-crafted in a unit
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
* to be included in the output. This time includes any restarts