You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PackStatistics.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*
  2. * Copyright (C) 2015, Google Inc.
  3. *
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Distribution License v1.0 which
  6. * accompanies this distribution, is reproduced below, and is
  7. * available at http://www.eclipse.org/org/documents/edl-v10.php
  8. *
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or
  12. * without modification, are permitted provided that the following
  13. * conditions are met:
  14. *
  15. * - Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * - Redistributions in binary form must reproduce the above
  19. * copyright notice, this list of conditions and the following
  20. * disclaimer in the documentation and/or other materials provided
  21. * with the distribution.
  22. *
  23. * - Neither the name of the Eclipse Foundation, Inc. nor the
  24. * names of its contributors may be used to endorse or promote
  25. * products derived from this software without specific prior
  26. * written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  29. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  30. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  31. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  33. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  35. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  36. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  37. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  39. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  40. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41. */
  42. package org.eclipse.jgit.storage.pack;
  43. import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
  44. import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
  45. import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
  46. import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
  47. import java.text.MessageFormat;
  48. import java.util.HashMap;
  49. import java.util.List;
  50. import java.util.Map;
  51. import java.util.Set;
  52. import org.eclipse.jgit.internal.JGitText;
  53. import org.eclipse.jgit.internal.storage.pack.CachedPack;
  54. import org.eclipse.jgit.lib.ObjectId;
  55. /**
  56. * Statistics about {@link org.eclipse.jgit.internal.storage.pack.PackWriter}
  57. * pack creation.
  58. *
  59. * @since 4.1
  60. */
  61. public class PackStatistics {
  62. /**
  63. * Statistics about a single type of object (commits, tags, trees and
  64. * blobs).
  65. */
  66. public static class ObjectType {
  67. /**
  68. * POJO for accumulating the ObjectType statistics.
  69. */
  70. public static class Accumulator {
  71. /** Count of objects of this type. */
  72. public long cntObjects;
  73. /** Count of deltas of this type. */
  74. public long cntDeltas;
  75. /** Count of reused objects of this type. */
  76. public long reusedObjects;
  77. /** Count of reused deltas of this type. */
  78. public long reusedDeltas;
  79. /** Count of bytes for all objects of this type. */
  80. public long bytes;
  81. /** Count of delta bytes for objects of this type. */
  82. public long deltaBytes;
  83. }
  84. private ObjectType.Accumulator objectType;
  85. /**
  86. * Creates a new {@link ObjectType} object from the accumulator.
  87. *
  88. * @param accumulator
  89. * the accumulator of the statistics
  90. */
  91. public ObjectType(ObjectType.Accumulator accumulator) {
  92. objectType = accumulator;
  93. }
  94. /**
  95. * @return total number of objects output. This total includes the value
  96. * of {@link #getDeltas()}.
  97. */
  98. public long getObjects() {
  99. return objectType.cntObjects;
  100. }
  101. /**
  102. * @return total number of deltas output. This may be lower than the
  103. * actual number of deltas if a cached pack was reused.
  104. */
  105. public long getDeltas() {
  106. return objectType.cntDeltas;
  107. }
  108. /**
  109. * @return number of objects whose existing representation was reused in
  110. * the output. This count includes {@link #getReusedDeltas()}.
  111. */
  112. public long getReusedObjects() {
  113. return objectType.reusedObjects;
  114. }
  115. /**
  116. * @return number of deltas whose existing representation was reused in
  117. * the output, as their base object was also output or was
  118. * assumed present for a thin pack. This may be lower than the
  119. * actual number of reused deltas if a cached pack was reused.
  120. */
  121. public long getReusedDeltas() {
  122. return objectType.reusedDeltas;
  123. }
  124. /**
  125. * @return total number of bytes written. This size includes the object
  126. * headers as well as the compressed data. This size also
  127. * includes all of {@link #getDeltaBytes()}.
  128. */
  129. public long getBytes() {
  130. return objectType.bytes;
  131. }
  132. /**
  133. * @return number of delta bytes written. This size includes the object
  134. * headers for the delta objects.
  135. */
  136. public long getDeltaBytes() {
  137. return objectType.deltaBytes;
  138. }
  139. }
  140. /**
  141. * POJO for accumulating the statistics.
  142. */
  143. public static class Accumulator {
  144. /** The set of objects to be included in the pack. */
  145. public Set<ObjectId> interestingObjects;
  146. /** The set of objects to be excluded from the pack. */
  147. public Set<ObjectId> uninterestingObjects;
  148. /** The collection of reused packs in the upload. */
  149. public List<CachedPack> reusedPacks;
  150. /** If a shallow pack, the depth in commits. */
  151. public int depth;
  152. /**
  153. * The count of objects in the pack that went through the delta search
  154. * process in order to find a potential delta base.
  155. */
  156. public int deltaSearchNonEdgeObjects;
  157. /**
  158. * The count of objects in the pack that went through delta base search
  159. * and found a suitable base. This is a subset of
  160. * deltaSearchNonEdgeObjects.
  161. */
  162. public int deltasFound;
  163. /** The total count of objects in the pack. */
  164. public long totalObjects;
  165. /**
  166. * The count of objects that needed to be discovered through an object
  167. * walk because they were not found in bitmap indices.
  168. */
  169. public long bitmapIndexMisses;
  170. /** The total count of deltas output. */
  171. public long totalDeltas;
  172. /** The count of reused objects in the pack. */
  173. public long reusedObjects;
  174. /** The count of reused deltas in the pack. */
  175. public long reusedDeltas;
  176. /** The count of total bytes in the pack. */
  177. public long totalBytes;
  178. /** The size of the thin pack in bytes, if a thin pack was generated. */
  179. public long thinPackBytes;
  180. /** Time in ms spent counting the objects that will go into the pack. */
  181. public long timeCounting;
  182. /** Time in ms spent searching for objects to reuse. */
  183. public long timeSearchingForReuse;
  184. /** Time in ms spent searching for sizes of objects. */
  185. public long timeSearchingForSizes;
  186. /** Time in ms spent compressing the pack. */
  187. public long timeCompressing;
  188. /** Time in ms spent writing the pack. */
  189. public long timeWriting;
  190. /**
  191. * Statistics about each object type in the pack (commits, tags, trees
  192. * and blobs.)
  193. */
  194. public ObjectType.Accumulator[] objectTypes;
  195. {
  196. objectTypes = new ObjectType.Accumulator[5];
  197. objectTypes[OBJ_COMMIT] = new ObjectType.Accumulator();
  198. objectTypes[OBJ_TREE] = new ObjectType.Accumulator();
  199. objectTypes[OBJ_BLOB] = new ObjectType.Accumulator();
  200. objectTypes[OBJ_TAG] = new ObjectType.Accumulator();
  201. }
  202. }
  203. private Accumulator statistics;
  204. /**
  205. * Creates a new {@link PackStatistics} object from the accumulator.
  206. *
  207. * @param accumulator
  208. * the accumulator of the statistics
  209. */
  210. public PackStatistics(Accumulator accumulator) {
  211. // Note: PackStatistics directly serves up the collections in the
  212. // accumulator.
  213. statistics = accumulator;
  214. }
  215. /**
  216. * @return unmodifiable collection of objects to be included in the pack.
  217. * May be {@code null} if the pack was hand-crafted in a unit test.
  218. */
  219. public Set<ObjectId> getInterestingObjects() {
  220. return statistics.interestingObjects;
  221. }
  222. /**
  223. * @return unmodifiable collection of objects that should be excluded from
  224. * the pack, as the peer that will receive the pack already has
  225. * these objects.
  226. */
  227. public Set<ObjectId> getUninterestingObjects() {
  228. return statistics.uninterestingObjects;
  229. }
  230. /**
  231. * @return unmodifiable list of the cached packs that were reused in the
  232. * output, if any were selected for reuse.
  233. */
  234. public List<CachedPack> getReusedPacks() {
  235. return statistics.reusedPacks;
  236. }
  237. /**
  238. * @return number of objects in the output pack that went through the delta
  239. * search process in order to find a potential delta base.
  240. */
  241. public int getDeltaSearchNonEdgeObjects() {
  242. return statistics.deltaSearchNonEdgeObjects;
  243. }
  244. /**
  245. * @return number of objects in the output pack that went through delta base
  246. * search and found a suitable base. This is a subset of
  247. * {@link #getDeltaSearchNonEdgeObjects()}.
  248. */
  249. public int getDeltasFound() {
  250. return statistics.deltasFound;
  251. }
  252. /**
  253. * @return total number of objects output. This total includes the value of
  254. * {@link #getTotalDeltas()}.
  255. */
  256. public long getTotalObjects() {
  257. return statistics.totalObjects;
  258. }
  259. /**
  260. * @return the count of objects that needed to be discovered through an
  261. * object walk because they were not found in bitmap indices.
  262. * Returns -1 if no bitmap indices were found.
  263. */
  264. public long getBitmapIndexMisses() {
  265. return statistics.bitmapIndexMisses;
  266. }
  267. /**
  268. * @return total number of deltas output. This may be lower than the actual
  269. * number of deltas if a cached pack was reused.
  270. */
  271. public long getTotalDeltas() {
  272. return statistics.totalDeltas;
  273. }
  274. /**
  275. * @return number of objects whose existing representation was reused in the
  276. * output. This count includes {@link #getReusedDeltas()}.
  277. */
  278. public long getReusedObjects() {
  279. return statistics.reusedObjects;
  280. }
  281. /**
  282. * @return number of deltas whose existing representation was reused in the
  283. * output, as their base object was also output or was assumed
  284. * present for a thin pack. This may be lower than the actual number
  285. * of reused deltas if a cached pack was reused.
  286. */
  287. public long getReusedDeltas() {
  288. return statistics.reusedDeltas;
  289. }
  290. /**
  291. * @return total number of bytes written. This size includes the pack
  292. * header, trailer, thin pack, and reused cached pack(s).
  293. */
  294. public long getTotalBytes() {
  295. return statistics.totalBytes;
  296. }
  297. /**
  298. * @return size of the thin pack in bytes, if a thin pack was generated. A
  299. * thin pack is created when the client already has objects and some
  300. * deltas are created against those objects, or if a cached pack is
  301. * being used and some deltas will reference objects in the cached
  302. * pack. This size does not include the pack header or trailer.
  303. */
  304. public long getThinPackBytes() {
  305. return statistics.thinPackBytes;
  306. }
  307. /**
  308. * @param typeCode
  309. * object type code, e.g. OBJ_COMMIT or OBJ_TREE.
  310. * @return information about this type of object in the pack.
  311. */
  312. public ObjectType byObjectType(int typeCode) {
  313. return new ObjectType(statistics.objectTypes[typeCode]);
  314. }
  315. /** @return true if the resulting pack file was a shallow pack. */
  316. public boolean isShallow() {
  317. return statistics.depth > 0;
  318. }
  319. /** @return depth (in commits) the pack includes if shallow. */
  320. public int getDepth() {
  321. return statistics.depth;
  322. }
  323. /**
  324. * @return time in milliseconds spent enumerating the objects that need to
  325. * be included in the output. This time includes any restarts that
  326. * occur when a cached pack is selected for reuse.
  327. */
  328. public long getTimeCounting() {
  329. return statistics.timeCounting;
  330. }
  331. /**
  332. * @return time in milliseconds spent matching existing representations
  333. * against objects that will be transmitted, or that the client can
  334. * be assumed to already have.
  335. */
  336. public long getTimeSearchingForReuse() {
  337. return statistics.timeSearchingForReuse;
  338. }
  339. /**
  340. * @return time in milliseconds spent finding the sizes of all objects that
  341. * will enter the delta compression search window. The sizes need to
  342. * be known to better match similar objects together and improve
  343. * delta compression ratios.
  344. */
  345. public long getTimeSearchingForSizes() {
  346. return statistics.timeSearchingForSizes;
  347. }
  348. /**
  349. * @return time in milliseconds spent on delta compression. This is observed
  350. * wall-clock time and does not accurately track CPU time used when
  351. * multiple threads were used to perform the delta compression.
  352. */
  353. public long getTimeCompressing() {
  354. return statistics.timeCompressing;
  355. }
  356. /**
  357. * @return time in milliseconds spent writing the pack output, from start of
  358. * header until end of trailer. The transfer speed can be
  359. * approximated by dividing {@link #getTotalBytes()} by this value.
  360. */
  361. public long getTimeWriting() {
  362. return statistics.timeWriting;
  363. }
  364. /** @return total time spent processing this pack. */
  365. public long getTimeTotal() {
  366. return statistics.timeCounting + statistics.timeSearchingForReuse
  367. + statistics.timeSearchingForSizes + statistics.timeCompressing
  368. + statistics.timeWriting;
  369. }
  370. /**
  371. * @return get the average output speed in terms of bytes-per-second.
  372. * {@code getTotalBytes() / (getTimeWriting() / 1000.0)}.
  373. */
  374. public double getTransferRate() {
  375. return getTotalBytes() / (getTimeWriting() / 1000.0);
  376. }
  377. /** @return formatted message string for display to clients. */
  378. public String getMessage() {
  379. return MessageFormat.format(JGitText.get().packWriterStatistics,
  380. Long.valueOf(statistics.totalObjects),
  381. Long.valueOf(statistics.totalDeltas),
  382. Long.valueOf(statistics.reusedObjects),
  383. Long.valueOf(statistics.reusedDeltas));
  384. }
  385. /** @return a map containing ObjectType statistics. */
  386. public Map<Integer, ObjectType> getObjectTypes() {
  387. HashMap<Integer, ObjectType> map = new HashMap<>();
  388. map.put(Integer.valueOf(OBJ_BLOB), new ObjectType(
  389. statistics.objectTypes[OBJ_BLOB]));
  390. map.put(Integer.valueOf(OBJ_COMMIT), new ObjectType(
  391. statistics.objectTypes[OBJ_COMMIT]));
  392. map.put(Integer.valueOf(OBJ_TAG), new ObjectType(
  393. statistics.objectTypes[OBJ_TAG]));
  394. map.put(Integer.valueOf(OBJ_TREE), new ObjectType(
  395. statistics.objectTypes[OBJ_TREE]));
  396. return map;
  397. }
  398. }