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 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  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. /*
  93. * For efficiency this wraps and serves up the Accumulator object
  94. * rather than making a deep clone. Normal usage of PackWriter is to
  95. * create a single pack/index/bitmap and only call getStatistics()
  96. * after all work is complete.
  97. */
  98. objectType = accumulator;
  99. }
  100. /**
  101. * @return total number of objects output. This total includes the value
  102. * of {@link #getDeltas()}.
  103. */
  104. public long getObjects() {
  105. return objectType.cntObjects;
  106. }
  107. /**
  108. * @return total number of deltas output. This may be lower than the
  109. * actual number of deltas if a cached pack was reused.
  110. */
  111. public long getDeltas() {
  112. return objectType.cntDeltas;
  113. }
  114. /**
  115. * @return number of objects whose existing representation was reused in
  116. * the output. This count includes {@link #getReusedDeltas()}.
  117. */
  118. public long getReusedObjects() {
  119. return objectType.reusedObjects;
  120. }
  121. /**
  122. * @return number of deltas whose existing representation was reused in
  123. * the output, as their base object was also output or was
  124. * assumed present for a thin pack. This may be lower than the
  125. * actual number of reused deltas if a cached pack was reused.
  126. */
  127. public long getReusedDeltas() {
  128. return objectType.reusedDeltas;
  129. }
  130. /**
  131. * @return total number of bytes written. This size includes the object
  132. * headers as well as the compressed data. This size also
  133. * includes all of {@link #getDeltaBytes()}.
  134. */
  135. public long getBytes() {
  136. return objectType.bytes;
  137. }
  138. /**
  139. * @return number of delta bytes written. This size includes the object
  140. * headers for the delta objects.
  141. */
  142. public long getDeltaBytes() {
  143. return objectType.deltaBytes;
  144. }
  145. }
  146. /**
  147. * POJO for accumulating the statistics.
  148. */
  149. public static class Accumulator {
  150. /**
  151. * The count of references in the ref advertisement.
  152. *
  153. * @since 4.11
  154. */
  155. public long advertised;
  156. /**
  157. * The count of client wants.
  158. *
  159. * @since 4.11
  160. */
  161. public long wants;
  162. /**
  163. * The count of client haves.
  164. *
  165. * @since 4.11
  166. */
  167. public long haves;
  168. /**
  169. * The count of wants that were not advertised by the server.
  170. *
  171. * @since 5.10
  172. */
  173. public long notAdvertisedWants;
  174. /**
  175. * Time in ms spent in the negotiation phase. For non-bidirectional
  176. * transports (e.g., HTTP), this is only for the final request that
  177. * sends back the pack file.
  178. *
  179. * @since 4.11
  180. */
  181. public long timeNegotiating;
  182. /** The set of objects to be included in the pack. */
  183. public Set<ObjectId> interestingObjects;
  184. /** The set of objects to be excluded from the pack. */
  185. public Set<ObjectId> uninterestingObjects;
  186. /** The set of shallow commits on the client. */
  187. public Set<ObjectId> clientShallowCommits;
  188. /** The collection of reused packs in the upload. */
  189. public List<CachedPack> reusedPacks;
  190. /** Commits with no parents. */
  191. public Set<ObjectId> rootCommits;
  192. /** If a shallow pack, the depth in commits. */
  193. public int depth;
  194. /**
  195. * The count of objects in the pack that went through the delta search
  196. * process in order to find a potential delta base.
  197. */
  198. public int deltaSearchNonEdgeObjects;
  199. /**
  200. * The count of objects in the pack that went through delta base search
  201. * and found a suitable base. This is a subset of
  202. * deltaSearchNonEdgeObjects.
  203. */
  204. public int deltasFound;
  205. /** The total count of objects in the pack. */
  206. public long totalObjects;
  207. /**
  208. * The count of objects that needed to be discovered through an object
  209. * walk because they were not found in bitmap indices.
  210. */
  211. public long bitmapIndexMisses;
  212. /** The total count of deltas output. */
  213. public long totalDeltas;
  214. /** The count of reused objects in the pack. */
  215. public long reusedObjects;
  216. /** The count of reused deltas in the pack. */
  217. public long reusedDeltas;
  218. /** The count of total bytes in the pack. */
  219. public long totalBytes;
  220. /** The size of the thin pack in bytes, if a thin pack was generated. */
  221. public long thinPackBytes;
  222. /** Time in ms spent counting the objects that will go into the pack. */
  223. public long timeCounting;
  224. /** Time in ms spent searching for objects to reuse. */
  225. public long timeSearchingForReuse;
  226. /** Time in ms spent searching for sizes of objects. */
  227. public long timeSearchingForSizes;
  228. /** Time in ms spent compressing the pack. */
  229. public long timeCompressing;
  230. /** Time in ms spent writing the pack. */
  231. public long timeWriting;
  232. /** Time in ms spent checking reachability.
  233. *
  234. * @since 5.10
  235. */
  236. public long reachabilityCheckDuration;
  237. /** Number of trees traversed in the walk when writing the pack.
  238. *
  239. * @since 5.4
  240. */
  241. public long treesTraversed;
  242. /**
  243. * Amount of packfile uris sent to the client to download via HTTP.
  244. *
  245. * @since 5.6
  246. */
  247. public long offloadedPackfiles;
  248. /**
  249. * Total size (in bytes) offloaded to HTTP downloads.
  250. *
  251. * @since 5.6
  252. */
  253. public long offloadedPackfileSize;
  254. /**
  255. * Statistics about each object type in the pack (commits, tags, trees
  256. * and blobs.)
  257. */
  258. public ObjectType.Accumulator[] objectTypes;
  259. {
  260. objectTypes = new ObjectType.Accumulator[5];
  261. objectTypes[OBJ_COMMIT] = new ObjectType.Accumulator();
  262. objectTypes[OBJ_TREE] = new ObjectType.Accumulator();
  263. objectTypes[OBJ_BLOB] = new ObjectType.Accumulator();
  264. objectTypes[OBJ_TAG] = new ObjectType.Accumulator();
  265. }
  266. }
  267. private Accumulator statistics;
  268. /**
  269. * Creates a new {@link org.eclipse.jgit.storage.pack.PackStatistics} object
  270. * from the accumulator.
  271. *
  272. * @param accumulator
  273. * the accumulator of the statistics
  274. */
  275. public PackStatistics(Accumulator accumulator) {
  276. /*
  277. * For efficiency this wraps and serves up the Accumulator object rather
  278. * than making a deep clone. Normal usage of PackWriter is to create a
  279. * single pack/index/bitmap and only call getStatistics() after all work
  280. * is complete.
  281. */
  282. statistics = accumulator;
  283. }
  284. /**
  285. * Get the count of references in the ref advertisement.
  286. *
  287. * @return count of refs in the ref advertisement.
  288. * @since 4.11
  289. */
  290. public long getAdvertised() {
  291. return statistics.advertised;
  292. }
  293. /**
  294. * Get the count of client wants.
  295. *
  296. * @return count of client wants.
  297. * @since 4.11
  298. */
  299. public long getWants() {
  300. return statistics.wants;
  301. }
  302. /**
  303. * Get the count of client haves.
  304. *
  305. * @return count of client haves.
  306. * @since 4.11
  307. */
  308. public long getHaves() {
  309. return statistics.haves;
  310. }
  311. /**
  312. * Get the count of client wants that were not advertised by the server.
  313. *
  314. * @return count of client wants that were not advertised by the server.
  315. * @since 5.10
  316. */
  317. public long getNotAdvertisedWants() {
  318. return statistics.notAdvertisedWants;
  319. }
  320. /**
  321. * Time in ms spent in the negotiation phase. For non-bidirectional
  322. * transports (e.g., HTTP), this is only for the final request that sends
  323. * back the pack file.
  324. *
  325. * @return time for ref advertisement in ms.
  326. * @since 4.11
  327. */
  328. public long getTimeNegotiating() {
  329. return statistics.timeNegotiating;
  330. }
  331. /**
  332. * Get unmodifiable collection of objects to be included in the pack.
  333. *
  334. * @return unmodifiable collection of objects to be included in the pack.
  335. * May be {@code null} if the pack was hand-crafted in a unit test.
  336. */
  337. public Set<ObjectId> getInterestingObjects() {
  338. return statistics.interestingObjects;
  339. }
  340. /**
  341. * Get unmodifiable collection of objects that should be excluded from the
  342. * pack
  343. *
  344. * @return unmodifiable collection of objects that should be excluded from
  345. * the pack, as the peer that will receive the pack already has
  346. * these objects.
  347. */
  348. public Set<ObjectId> getUninterestingObjects() {
  349. return statistics.uninterestingObjects;
  350. }
  351. /**
  352. * Get unmodifiable collection of objects that were shallow commits on the
  353. * client.
  354. *
  355. * @return unmodifiable collection of objects that were shallow commits on
  356. * the client.
  357. */
  358. public Set<ObjectId> getClientShallowCommits() {
  359. return statistics.clientShallowCommits;
  360. }
  361. /**
  362. * Get unmodifiable list of the cached packs that were reused in the output
  363. *
  364. * @return unmodifiable list of the cached packs that were reused in the
  365. * output, if any were selected for reuse.
  366. */
  367. public List<CachedPack> getReusedPacks() {
  368. return statistics.reusedPacks;
  369. }
  370. /**
  371. * Get unmodifiable collection of the root commits of the history.
  372. *
  373. * @return unmodifiable collection of the root commits of the history.
  374. */
  375. public Set<ObjectId> getRootCommits() {
  376. return statistics.rootCommits;
  377. }
  378. /**
  379. * Get number of objects in the output pack that went through the delta
  380. * search process in order to find a potential delta base.
  381. *
  382. * @return number of objects in the output pack that went through the delta
  383. * search process in order to find a potential delta base.
  384. */
  385. public int getDeltaSearchNonEdgeObjects() {
  386. return statistics.deltaSearchNonEdgeObjects;
  387. }
  388. /**
  389. * Get number of objects in the output pack that went through delta base
  390. * search and found a suitable base.
  391. *
  392. * @return number of objects in the output pack that went through delta base
  393. * search and found a suitable base. This is a subset of
  394. * {@link #getDeltaSearchNonEdgeObjects()}.
  395. */
  396. public int getDeltasFound() {
  397. return statistics.deltasFound;
  398. }
  399. /**
  400. * Get total number of objects output.
  401. *
  402. * @return total number of objects output. This total includes the value of
  403. * {@link #getTotalDeltas()}.
  404. */
  405. public long getTotalObjects() {
  406. return statistics.totalObjects;
  407. }
  408. /**
  409. * Get the count of objects that needed to be discovered through an object
  410. * walk because they were not found in bitmap indices.
  411. *
  412. * @return the count of objects that needed to be discovered through an
  413. * object walk because they were not found in bitmap indices.
  414. * Returns -1 if no bitmap indices were found.
  415. */
  416. public long getBitmapIndexMisses() {
  417. return statistics.bitmapIndexMisses;
  418. }
  419. /**
  420. * Get total number of deltas output.
  421. *
  422. * @return total number of deltas output. This may be lower than the actual
  423. * number of deltas if a cached pack was reused.
  424. */
  425. public long getTotalDeltas() {
  426. return statistics.totalDeltas;
  427. }
  428. /**
  429. * Get number of objects whose existing representation was reused in the
  430. * output.
  431. *
  432. * @return number of objects whose existing representation was reused in the
  433. * output. This count includes {@link #getReusedDeltas()}.
  434. */
  435. public long getReusedObjects() {
  436. return statistics.reusedObjects;
  437. }
  438. /**
  439. * Get number of deltas whose existing representation was reused in the
  440. * output.
  441. *
  442. * @return number of deltas whose existing representation was reused in the
  443. * output, as their base object was also output or was assumed
  444. * present for a thin pack. This may be lower than the actual number
  445. * of reused deltas if a cached pack was reused.
  446. */
  447. public long getReusedDeltas() {
  448. return statistics.reusedDeltas;
  449. }
  450. /**
  451. * Get total number of bytes written.
  452. *
  453. * @return total number of bytes written. This size includes the pack
  454. * header, trailer, thin pack, and reused cached pack(s).
  455. */
  456. public long getTotalBytes() {
  457. return statistics.totalBytes;
  458. }
  459. /**
  460. * Get size of the thin pack in bytes.
  461. *
  462. * @return size of the thin pack in bytes, if a thin pack was generated. A
  463. * thin pack is created when the client already has objects and some
  464. * deltas are created against those objects, or if a cached pack is
  465. * being used and some deltas will reference objects in the cached
  466. * pack. This size does not include the pack header or trailer.
  467. */
  468. public long getThinPackBytes() {
  469. return statistics.thinPackBytes;
  470. }
  471. /**
  472. * Get information about this type of object in the pack.
  473. *
  474. * @param typeCode
  475. * object type code, e.g. OBJ_COMMIT or OBJ_TREE.
  476. * @return information about this type of object in the pack.
  477. */
  478. public ObjectType byObjectType(int typeCode) {
  479. return new ObjectType(statistics.objectTypes[typeCode]);
  480. }
  481. /**
  482. * Whether the resulting pack file was a shallow pack.
  483. *
  484. * @return {@code true} if the resulting pack file was a shallow pack.
  485. */
  486. public boolean isShallow() {
  487. return statistics.depth > 0;
  488. }
  489. /**
  490. * Get depth (in commits) the pack includes if shallow.
  491. *
  492. * @return depth (in commits) the pack includes if shallow.
  493. */
  494. public int getDepth() {
  495. return statistics.depth;
  496. }
  497. /**
  498. * Get time in milliseconds spent enumerating the objects that need to be
  499. * included in the output.
  500. *
  501. * @return time in milliseconds spent enumerating the objects that need to
  502. * be included in the output. This time includes any restarts that
  503. * occur when a cached pack is selected for reuse.
  504. */
  505. public long getTimeCounting() {
  506. return statistics.timeCounting;
  507. }
  508. /**
  509. * Get time in milliseconds spent matching existing representations against
  510. * objects that will be transmitted.
  511. *
  512. * @return time in milliseconds spent matching existing representations
  513. * against objects that will be transmitted, or that the client can
  514. * be assumed to already have.
  515. */
  516. public long getTimeSearchingForReuse() {
  517. return statistics.timeSearchingForReuse;
  518. }
  519. /**
  520. * Get time in milliseconds spent finding the sizes of all objects that will
  521. * enter the delta compression search window.
  522. *
  523. * @return time in milliseconds spent finding the sizes of all objects that
  524. * will enter the delta compression search window. The sizes need to
  525. * be known to better match similar objects together and improve
  526. * delta compression ratios.
  527. */
  528. public long getTimeSearchingForSizes() {
  529. return statistics.timeSearchingForSizes;
  530. }
  531. /**
  532. * Get time in milliseconds spent on delta compression.
  533. *
  534. * @return time in milliseconds spent on delta compression. This is observed
  535. * wall-clock time and does not accurately track CPU time used when
  536. * multiple threads were used to perform the delta compression.
  537. */
  538. public long getTimeCompressing() {
  539. return statistics.timeCompressing;
  540. }
  541. /**
  542. * Get time in milliseconds spent writing the pack output, from start of
  543. * header until end of trailer.
  544. *
  545. * @return time in milliseconds spent writing the pack output, from start of
  546. * header until end of trailer. The transfer speed can be
  547. * approximated by dividing {@link #getTotalBytes()} by this value.
  548. */
  549. public long getTimeWriting() {
  550. return statistics.timeWriting;
  551. }
  552. /**
  553. * Get time in milliseconds spent checking if the client has access to the
  554. * commits they are requesting.
  555. *
  556. * @return time in milliseconds spent checking if the client has access to the
  557. * commits they are requesting.
  558. * @since 5.10
  559. */
  560. public long getReachabilityCheckDuration() {
  561. return statistics.reachabilityCheckDuration;
  562. }
  563. /**
  564. * @return number of trees traversed in the walk when writing the pack.
  565. * @since 5.4
  566. */
  567. public long getTreesTraversed() {
  568. return statistics.treesTraversed;
  569. }
  570. /**
  571. * @return amount of packfiles offloaded (sent as "packfile-uri")/
  572. * @since 5.6
  573. */
  574. public long getOffloadedPackfiles() {
  575. return statistics.offloadedPackfiles;
  576. }
  577. /**
  578. * @return total size (in bytes) offloaded to HTTP downloads.
  579. * @since 5.6
  580. */
  581. public long getOffloadedPackfilesSize() {
  582. return statistics.offloadedPackfileSize;
  583. }
  584. /**
  585. * Get total time spent processing this pack.
  586. *
  587. * @return total time spent processing this pack.
  588. */
  589. public long getTimeTotal() {
  590. return statistics.timeCounting + statistics.timeSearchingForReuse
  591. + statistics.timeSearchingForSizes + statistics.timeCompressing
  592. + statistics.timeWriting;
  593. }
  594. /**
  595. * Get the average output speed in terms of bytes-per-second.
  596. *
  597. * @return the average output speed in terms of bytes-per-second.
  598. * {@code getTotalBytes() / (getTimeWriting() / 1000.0)}.
  599. */
  600. public double getTransferRate() {
  601. return getTotalBytes() / (getTimeWriting() / 1000.0);
  602. }
  603. /**
  604. * Get formatted message string for display to clients.
  605. *
  606. * @return formatted message string for display to clients.
  607. */
  608. public String getMessage() {
  609. return MessageFormat.format(JGitText.get().packWriterStatistics,
  610. Long.valueOf(statistics.totalObjects),
  611. Long.valueOf(statistics.totalDeltas),
  612. Long.valueOf(statistics.reusedObjects),
  613. Long.valueOf(statistics.reusedDeltas));
  614. }
  615. /**
  616. * Get a map containing ObjectType statistics.
  617. *
  618. * @return a map containing ObjectType statistics.
  619. */
  620. public Map<Integer, ObjectType> getObjectTypes() {
  621. HashMap<Integer, ObjectType> map = new HashMap<>();
  622. map.put(Integer.valueOf(OBJ_BLOB), new ObjectType(
  623. statistics.objectTypes[OBJ_BLOB]));
  624. map.put(Integer.valueOf(OBJ_COMMIT), new ObjectType(
  625. statistics.objectTypes[OBJ_COMMIT]));
  626. map.put(Integer.valueOf(OBJ_TAG), new ObjectType(
  627. statistics.objectTypes[OBJ_TAG]));
  628. map.put(Integer.valueOf(OBJ_TREE), new ObjectType(
  629. statistics.objectTypes[OBJ_TREE]));
  630. return map;
  631. }
  632. }