797 :``readdensity``: density of useful bytes in the data read from the disk |
795 :``readdensity``: density of useful bytes in the data read from the disk |
798 :``srchunks``: in how many data hunks the whole revision would be read |
796 :``srchunks``: in how many data hunks the whole revision would be read |
799 |
797 |
800 The sparse read can be enabled with experimental.sparse-read = True |
798 The sparse read can be enabled with experimental.sparse-read = True |
801 """ |
799 """ |
802 r = cmdutil.openrevlog( |
800 revlog = cmdutil.openrevlog( |
803 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts) |
801 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts) |
804 ) |
802 ) |
805 index = r.index |
|
806 start = r.start |
|
807 length = r.length |
|
808 generaldelta = r.delta_config.general_delta |
|
809 withsparseread = r.data_config.with_sparse_read |
|
810 |
|
811 # security to avoid crash on corrupted revlogs |
|
812 total_revs = len(index) |
|
813 |
|
814 chain_size_cache = {} |
|
815 |
|
816 def revinfo(rev): |
|
817 e = index[rev] |
|
818 compsize = e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] |
|
819 uncompsize = e[revlog_constants.ENTRY_DATA_UNCOMPRESSED_LENGTH] |
|
820 |
|
821 base = e[revlog_constants.ENTRY_DELTA_BASE] |
|
822 p1 = e[revlog_constants.ENTRY_PARENT_1] |
|
823 p2 = e[revlog_constants.ENTRY_PARENT_2] |
|
824 |
|
825 # If the parents of a revision has an empty delta, we never try to delta |
|
826 # against that parent, but directly against the delta base of that |
|
827 # parent (recursively). It avoids adding a useless entry in the chain. |
|
828 # |
|
829 # However we need to detect that as a special case for delta-type, that |
|
830 # is not simply "other". |
|
831 p1_base = p1 |
|
832 if p1 != nullrev and p1 < total_revs: |
|
833 e1 = index[p1] |
|
834 while e1[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0: |
|
835 new_base = e1[revlog_constants.ENTRY_DELTA_BASE] |
|
836 if ( |
|
837 new_base == p1_base |
|
838 or new_base == nullrev |
|
839 or new_base >= total_revs |
|
840 ): |
|
841 break |
|
842 p1_base = new_base |
|
843 e1 = index[p1_base] |
|
844 p2_base = p2 |
|
845 if p2 != nullrev and p2 < total_revs: |
|
846 e2 = index[p2] |
|
847 while e2[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0: |
|
848 new_base = e2[revlog_constants.ENTRY_DELTA_BASE] |
|
849 if ( |
|
850 new_base == p2_base |
|
851 or new_base == nullrev |
|
852 or new_base >= total_revs |
|
853 ): |
|
854 break |
|
855 p2_base = new_base |
|
856 e2 = index[p2_base] |
|
857 |
|
858 if generaldelta: |
|
859 if base == p1: |
|
860 deltatype = b'p1' |
|
861 elif base == p2: |
|
862 deltatype = b'p2' |
|
863 elif base == rev: |
|
864 deltatype = b'base' |
|
865 elif base == p1_base: |
|
866 deltatype = b'skip1' |
|
867 elif base == p2_base: |
|
868 deltatype = b'skip2' |
|
869 elif r.issnapshot(rev): |
|
870 deltatype = b'snap' |
|
871 elif base == rev - 1: |
|
872 deltatype = b'prev' |
|
873 else: |
|
874 deltatype = b'other' |
|
875 else: |
|
876 if base == rev: |
|
877 deltatype = b'base' |
|
878 else: |
|
879 deltatype = b'prev' |
|
880 |
|
881 chain = r._deltachain(rev)[0] |
|
882 chain_size = 0 |
|
883 for iter_rev in reversed(chain): |
|
884 cached = chain_size_cache.get(iter_rev) |
|
885 if cached is not None: |
|
886 chain_size += cached |
|
887 break |
|
888 e = index[iter_rev] |
|
889 chain_size += e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] |
|
890 chain_size_cache[rev] = chain_size |
|
891 |
|
892 return p1, p2, compsize, uncompsize, deltatype, chain, chain_size |
|
893 |
|
894 fm = ui.formatter(b'debugdeltachain', pycompat.byteskwargs(opts)) |
803 fm = ui.formatter(b'debugdeltachain', pycompat.byteskwargs(opts)) |
895 |
804 |
896 fm.plain( |
805 lines = revlog_debug.debug_delta_chain(revlog) |
897 b' rev p1 p2 chain# chainlen prev delta ' |
806 # first entry is the header |
898 b'size rawsize chainsize ratio lindist extradist ' |
807 header = next(lines) |
899 b'extraratio' |
808 fm.plain(header) |
900 ) |
809 for entry in lines: |
901 if withsparseread: |
810 label = b' '.join(e[0] for e in entry) |
902 fm.plain(b' readsize largestblk rddensity srchunks') |
811 format = b' '.join(e[1] for e in entry) |
903 fm.plain(b'\n') |
812 values = [e[3] for e in entry] |
904 |
813 data = dict((e[2], e[3]) for e in entry) |
905 chainbases = {} |
|
906 for rev in r: |
|
907 p1, p2, comp, uncomp, deltatype, chain, chainsize = revinfo(rev) |
|
908 chainbase = chain[0] |
|
909 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1) |
|
910 basestart = start(chainbase) |
|
911 revstart = start(rev) |
|
912 lineardist = revstart + comp - basestart |
|
913 extradist = lineardist - chainsize |
|
914 try: |
|
915 prevrev = chain[-2] |
|
916 except IndexError: |
|
917 prevrev = -1 |
|
918 |
|
919 if uncomp != 0: |
|
920 chainratio = float(chainsize) / float(uncomp) |
|
921 else: |
|
922 chainratio = chainsize |
|
923 |
|
924 if chainsize != 0: |
|
925 extraratio = float(extradist) / float(chainsize) |
|
926 else: |
|
927 extraratio = extradist |
|
928 |
|
929 fm.startitem() |
814 fm.startitem() |
930 fm.write( |
815 fm.write(label, format, *values, **data) |
931 b'rev p1 p2 chainid chainlen prevrev deltatype compsize ' |
|
932 b'uncompsize chainsize chainratio lindist extradist ' |
|
933 b'extraratio', |
|
934 b'%7d %7d %7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f', |
|
935 rev, |
|
936 p1, |
|
937 p2, |
|
938 chainid, |
|
939 len(chain), |
|
940 prevrev, |
|
941 deltatype, |
|
942 comp, |
|
943 uncomp, |
|
944 chainsize, |
|
945 chainratio, |
|
946 lineardist, |
|
947 extradist, |
|
948 extraratio, |
|
949 rev=rev, |
|
950 chainid=chainid, |
|
951 chainlen=len(chain), |
|
952 prevrev=prevrev, |
|
953 deltatype=deltatype, |
|
954 compsize=comp, |
|
955 uncompsize=uncomp, |
|
956 chainsize=chainsize, |
|
957 chainratio=chainratio, |
|
958 lindist=lineardist, |
|
959 extradist=extradist, |
|
960 extraratio=extraratio, |
|
961 ) |
|
962 if withsparseread: |
|
963 readsize = 0 |
|
964 largestblock = 0 |
|
965 srchunks = 0 |
|
966 |
|
967 for revschunk in deltautil.slicechunk(r, chain): |
|
968 srchunks += 1 |
|
969 blkend = start(revschunk[-1]) + length(revschunk[-1]) |
|
970 blksize = blkend - start(revschunk[0]) |
|
971 |
|
972 readsize += blksize |
|
973 if largestblock < blksize: |
|
974 largestblock = blksize |
|
975 |
|
976 if readsize: |
|
977 readdensity = float(chainsize) / float(readsize) |
|
978 else: |
|
979 readdensity = 1 |
|
980 |
|
981 fm.write( |
|
982 b'readsize largestblock readdensity srchunks', |
|
983 b' %10d %10d %9.5f %8d', |
|
984 readsize, |
|
985 largestblock, |
|
986 readdensity, |
|
987 srchunks, |
|
988 readsize=readsize, |
|
989 largestblock=largestblock, |
|
990 readdensity=readdensity, |
|
991 srchunks=srchunks, |
|
992 ) |
|
993 |
|
994 fm.plain(b'\n') |
816 fm.plain(b'\n') |
995 |
|
996 fm.end() |
817 fm.end() |
997 |
818 |
998 |
819 |
999 @command( |
820 @command( |
1000 b'debug-delta-find', |
821 b'debug-delta-find', |