PackStatistics.java
- /*
- * Copyright (C) 2015, Google Inc.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- package org.eclipse.jgit.storage.pack;
- import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
- import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
- import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
- import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
- import java.text.MessageFormat;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import org.eclipse.jgit.internal.JGitText;
- import org.eclipse.jgit.internal.storage.pack.CachedPack;
- import org.eclipse.jgit.lib.ObjectId;
- /**
- * Statistics about {@link org.eclipse.jgit.internal.storage.pack.PackWriter}
- * pack creation.
- *
- * @since 4.1
- */
- public class PackStatistics {
- /**
- * Statistics about a single type of object (commits, tags, trees and
- * blobs).
- */
- public static class ObjectType {
- /**
- * POJO for accumulating the ObjectType statistics.
- */
- public static class Accumulator {
- /** Count of objects of this type. */
- public long cntObjects;
- /** Count of deltas of this type. */
- public long cntDeltas;
- /** Count of reused objects of this type. */
- public long reusedObjects;
- /** Count of reused deltas of this type. */
- public long reusedDeltas;
- /** Count of bytes for all objects of this type. */
- public long bytes;
- /** Count of delta bytes for objects of this type. */
- public long deltaBytes;
- }
- private ObjectType.Accumulator objectType;
- /**
- * Creates a new {@link ObjectType} object from the accumulator.
- *
- * @param accumulator
- * the accumulator of the statistics
- */
- public ObjectType(ObjectType.Accumulator accumulator) {
- /*
- * For efficiency this wraps and serves up the Accumulator object
- * rather than making a deep clone. Normal usage of PackWriter is to
- * create a single pack/index/bitmap and only call getStatistics()
- * after all work is complete.
- */
- objectType = accumulator;
- }
- /**
- * @return total number of objects output. This total includes the value
- * of {@link #getDeltas()}.
- */
- public long getObjects() {
- return objectType.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 objectType.cntDeltas;
- }
- /**
- * @return number of objects whose existing representation was reused in
- * the output. This count includes {@link #getReusedDeltas()}.
- */
- public long getReusedObjects() {
- return objectType.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 objectType.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 objectType.bytes;
- }
- /**
- * @return number of delta bytes written. This size includes the object
- * headers for the delta objects.
- */
- public long getDeltaBytes() {
- return objectType.deltaBytes;
- }
- }
- /**
- * 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;
- /** The set of objects to be excluded from the pack. */
- public Set<ObjectId> uninterestingObjects;
- /** The set of shallow commits on the client. */
- public Set<ObjectId> clientShallowCommits;
- /** The collection of reused packs in the upload. */
- public List<CachedPack> reusedPacks;
- /** Commits with no parents. */
- public Set<ObjectId> rootCommits;
- /** If a shallow pack, the depth in commits. */
- public int depth;
- /**
- * The count of objects in the pack that went through the delta search
- * process in order to find a potential delta base.
- */
- public int deltaSearchNonEdgeObjects;
- /**
- * The count of objects in the pack that went through delta base search
- * and found a suitable base. This is a subset of
- * deltaSearchNonEdgeObjects.
- */
- public int deltasFound;
- /** The total count of objects in the pack. */
- public long totalObjects;
- /**
- * The count of objects that needed to be discovered through an object
- * walk because they were not found in bitmap indices.
- */
- public long bitmapIndexMisses;
- /** The total count of deltas output. */
- public long totalDeltas;
- /** The count of reused objects in the pack. */
- public long reusedObjects;
- /** The count of reused deltas in the pack. */
- public long reusedDeltas;
- /** The count of total bytes in the pack. */
- public long totalBytes;
- /** The size of the thin pack in bytes, if a thin pack was generated. */
- public long thinPackBytes;
- /** Time in ms spent counting the objects that will go into the pack. */
- public long timeCounting;
- /** Time in ms spent searching for objects to reuse. */
- public long timeSearchingForReuse;
- /** Time in ms spent searching for sizes of objects. */
- public long timeSearchingForSizes;
- /** Time in ms spent compressing the pack. */
- public long timeCompressing;
- /** Time in ms spent writing the pack. */
- public long timeWriting;
- /** Number of trees traversed in the walk when writing the pack.
- * @since 5.4*/
- public long treesTraversed;
- /**
- * Statistics about each object type in the pack (commits, tags, trees
- * and blobs.)
- */
- public ObjectType.Accumulator[] objectTypes;
- {
- objectTypes = new ObjectType.Accumulator[5];
- objectTypes[OBJ_COMMIT] = new ObjectType.Accumulator();
- objectTypes[OBJ_TREE] = new ObjectType.Accumulator();
- objectTypes[OBJ_BLOB] = new ObjectType.Accumulator();
- objectTypes[OBJ_TAG] = new ObjectType.Accumulator();
- }
- }
- private Accumulator statistics;
- /**
- * Creates a new {@link org.eclipse.jgit.storage.pack.PackStatistics} object
- * from the accumulator.
- *
- * @param accumulator
- * the accumulator of the statistics
- */
- public PackStatistics(Accumulator accumulator) {
- /*
- * For efficiency this wraps and serves up the Accumulator object rather
- * than making a deep clone. Normal usage of PackWriter is to create a
- * single pack/index/bitmap and only call getStatistics() after all work
- * is complete.
- */
- 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.
- *
- * @return unmodifiable collection of objects to be included in the pack.
- * May be {@code null} if the pack was hand-crafted in a unit test.
- */
- public Set<ObjectId> getInterestingObjects() {
- return statistics.interestingObjects;
- }
- /**
- * Get unmodifiable collection of objects that should be excluded from the
- * pack
- *
- * @return unmodifiable collection of objects that should be excluded from
- * the pack, as the peer that will receive the pack already has
- * these objects.
- */
- public Set<ObjectId> getUninterestingObjects() {
- return statistics.uninterestingObjects;
- }
- /**
- * Get unmodifiable collection of objects that were shallow commits on the
- * client.
- *
- * @return unmodifiable collection of objects that were shallow commits on
- * the client.
- */
- public Set<ObjectId> getClientShallowCommits() {
- return statistics.clientShallowCommits;
- }
- /**
- * Get unmodifiable list of the cached packs that were reused in the output
- *
- * @return unmodifiable list of the cached packs that were reused in the
- * output, if any were selected for reuse.
- */
- public List<CachedPack> getReusedPacks() {
- return statistics.reusedPacks;
- }
- /**
- * Get unmodifiable collection of the root commits of the history.
- *
- * @return unmodifiable collection of the root commits of the history.
- */
- public Set<ObjectId> getRootCommits() {
- return statistics.rootCommits;
- }
- /**
- * Get number of objects in the output pack that went through the delta
- * search process in order to find a potential delta base.
- *
- * @return number of objects in the output pack that went through the delta
- * search process in order to find a potential delta base.
- */
- public int getDeltaSearchNonEdgeObjects() {
- return statistics.deltaSearchNonEdgeObjects;
- }
- /**
- * Get number of objects in the output pack that went through delta base
- * search and found a suitable base.
- *
- * @return number of objects in the output pack that went through delta base
- * search and found a suitable base. This is a subset of
- * {@link #getDeltaSearchNonEdgeObjects()}.
- */
- public int getDeltasFound() {
- return statistics.deltasFound;
- }
- /**
- * Get total number of objects output.
- *
- * @return total number of objects output. This total includes the value of
- * {@link #getTotalDeltas()}.
- */
- public long getTotalObjects() {
- return statistics.totalObjects;
- }
- /**
- * Get the count of objects that needed to be discovered through an object
- * walk because they were not found in bitmap indices.
- *
- * @return the count of objects that needed to be discovered through an
- * object walk because they were not found in bitmap indices.
- * Returns -1 if no bitmap indices were found.
- */
- public long getBitmapIndexMisses() {
- return statistics.bitmapIndexMisses;
- }
- /**
- * Get total number of deltas output.
- *
- * @return total number of deltas output. This may be lower than the actual
- * number of deltas if a cached pack was reused.
- */
- public long getTotalDeltas() {
- return statistics.totalDeltas;
- }
- /**
- * Get number of objects whose existing representation was reused in the
- * output.
- *
- * @return number of objects whose existing representation was reused in the
- * output. This count includes {@link #getReusedDeltas()}.
- */
- public long getReusedObjects() {
- return statistics.reusedObjects;
- }
- /**
- * Get number of deltas whose existing representation was reused in the
- * output.
- *
- * @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 statistics.reusedDeltas;
- }
- /**
- * Get total number of bytes written.
- *
- * @return total number of bytes written. This size includes the pack
- * header, trailer, thin pack, and reused cached pack(s).
- */
- public long getTotalBytes() {
- return statistics.totalBytes;
- }
- /**
- * Get size of the thin pack in bytes.
- *
- * @return size of the thin pack in bytes, if a thin pack was generated. A
- * thin pack is created when the client already has objects and some
- * deltas are created against those objects, or if a cached pack is
- * being used and some deltas will reference objects in the cached
- * pack. This size does not include the pack header or trailer.
- */
- public long getThinPackBytes() {
- return statistics.thinPackBytes;
- }
- /**
- * Get information about this type of object in the pack.
- *
- * @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 new ObjectType(statistics.objectTypes[typeCode]);
- }
- /**
- * Whether the resulting pack file was a shallow pack.
- *
- * @return {@code true} if the resulting pack file was a shallow pack.
- */
- public boolean isShallow() {
- return statistics.depth > 0;
- }
- /**
- * Get depth (in commits) the pack includes if shallow.
- *
- * @return depth (in commits) the pack includes if shallow.
- */
- public int getDepth() {
- return statistics.depth;
- }
- /**
- * Get time in milliseconds spent enumerating the objects that need to be
- * included in the output.
- *
- * @return time in milliseconds spent enumerating the objects that need to
- * be included in the output. This time includes any restarts that
- * occur when a cached pack is selected for reuse.
- */
- public long getTimeCounting() {
- return statistics.timeCounting;
- }
- /**
- * Get time in milliseconds spent matching existing representations against
- * objects that will be transmitted.
- *
- * @return time in milliseconds spent matching existing representations
- * against objects that will be transmitted, or that the client can
- * be assumed to already have.
- */
- public long getTimeSearchingForReuse() {
- return statistics.timeSearchingForReuse;
- }
- /**
- * Get time in milliseconds spent finding the sizes of all objects that will
- * enter the delta compression search window.
- *
- * @return time in milliseconds spent finding the sizes of all objects that
- * will enter the delta compression search window. The sizes need to
- * be known to better match similar objects together and improve
- * delta compression ratios.
- */
- public long getTimeSearchingForSizes() {
- return statistics.timeSearchingForSizes;
- }
- /**
- * Get time in milliseconds spent on delta compression.
- *
- * @return time in milliseconds spent on delta compression. This is observed
- * wall-clock time and does not accurately track CPU time used when
- * multiple threads were used to perform the delta compression.
- */
- public long getTimeCompressing() {
- return statistics.timeCompressing;
- }
- /**
- * Get time in milliseconds spent writing the pack output, from start of
- * header until end of trailer.
- *
- * @return time in milliseconds spent writing the pack output, from start of
- * header until end of trailer. The transfer speed can be
- * approximated by dividing {@link #getTotalBytes()} by this value.
- */
- public long getTimeWriting() {
- return statistics.timeWriting;
- }
- /**
- * @return number of trees traversed in the walk when writing the pack.
- * @since 5.4
- */
- public long getTreesTraversed() {
- return statistics.treesTraversed;
- }
- /**
- * Get total time spent processing this pack.
- *
- * @return total time spent processing this pack.
- */
- public long getTimeTotal() {
- return statistics.timeCounting + statistics.timeSearchingForReuse
- + statistics.timeSearchingForSizes + statistics.timeCompressing
- + statistics.timeWriting;
- }
- /**
- * Get the average output speed in terms of bytes-per-second.
- *
- * @return the average output speed in terms of bytes-per-second.
- * {@code getTotalBytes() / (getTimeWriting() / 1000.0)}.
- */
- public double getTransferRate() {
- return getTotalBytes() / (getTimeWriting() / 1000.0);
- }
- /**
- * Get formatted message string for display to clients.
- *
- * @return formatted message string for display to clients.
- */
- public String getMessage() {
- return MessageFormat.format(JGitText.get().packWriterStatistics,
- Long.valueOf(statistics.totalObjects),
- Long.valueOf(statistics.totalDeltas),
- Long.valueOf(statistics.reusedObjects),
- Long.valueOf(statistics.reusedDeltas));
- }
- /**
- * Get a map containing ObjectType statistics.
- *
- * @return a map containing ObjectType statistics.
- */
- public Map<Integer, ObjectType> getObjectTypes() {
- HashMap<Integer, ObjectType> map = new HashMap<>();
- map.put(Integer.valueOf(OBJ_BLOB), new ObjectType(
- statistics.objectTypes[OBJ_BLOB]));
- map.put(Integer.valueOf(OBJ_COMMIT), new ObjectType(
- statistics.objectTypes[OBJ_COMMIT]));
- map.put(Integer.valueOf(OBJ_TAG), new ObjectType(
- statistics.objectTypes[OBJ_TAG]));
- map.put(Integer.valueOf(OBJ_TREE), new ObjectType(
- statistics.objectTypes[OBJ_TREE]));
- return map;
- }
- }