Show More
@@ -1111,6 +1111,28 b' default = "65K"' | |||
|
1111 | 1111 | |
|
1112 | 1112 | [[items]] |
|
1113 | 1113 | section = "experimental" |
|
1114 | name = "revlog.uncompressed-cache.enabled" | |
|
1115 | default = true | |
|
1116 | experimental = true | |
|
1117 | documentation = """Enable some caching of uncompressed chunk, greatly boosting | |
|
1118 | performance at the cost of memory usage.""" | |
|
1119 | ||
|
1120 | [[items]] | |
|
1121 | section = "experimental" | |
|
1122 | name = "revlog.uncompressed-cache.factor" | |
|
1123 | default = 4 | |
|
1124 | experimental = true | |
|
1125 | documentation = """The size of the cache compared to the largest revision seen.""" | |
|
1126 | ||
|
1127 | [[items]] | |
|
1128 | section = "experimental" | |
|
1129 | name = "revlog.uncompressed-cache.count" | |
|
1130 | default = 10000 | |
|
1131 | experimental = true | |
|
1132 | documentation = """The number of chunk cached.""" | |
|
1133 | ||
|
1134 | [[items]] | |
|
1135 | section = "experimental" | |
|
1114 | 1136 | name = "stream-v3" |
|
1115 | 1137 | default = false |
|
1116 | 1138 |
@@ -1089,6 +1089,16 b' def resolverevlogstorevfsoptions(ui, req' | |||
|
1089 | 1089 | if chunkcachesize is not None: |
|
1090 | 1090 | data_config.chunk_cache_size = chunkcachesize |
|
1091 | 1091 | |
|
1092 | if ui.configbool(b'experimental', b'revlog.uncompressed-cache.enabled'): | |
|
1093 | factor = ui.configint( | |
|
1094 | b'experimental', b'revlog.uncompressed-cache.factor' | |
|
1095 | ) | |
|
1096 | count = ui.configint( | |
|
1097 | b'experimental', b'revlog.uncompressed-cache.count' | |
|
1098 | ) | |
|
1099 | data_config.uncompressed_cache_factor = factor | |
|
1100 | data_config.uncompressed_cache_count = count | |
|
1101 | ||
|
1092 | 1102 | delta_config.delta_both_parents = ui.configbool( |
|
1093 | 1103 | b'storage', b'revlog.optimize-delta-parent-choice' |
|
1094 | 1104 | ) |
@@ -295,6 +295,12 b' class DataConfig(_Config):' | |||
|
295 | 295 | # How much data to read and cache into the raw revlog data cache. |
|
296 | 296 | chunk_cache_size = attr.ib(default=65536) |
|
297 | 297 | |
|
298 | # The size of the uncompressed cache compared to the largest revision seen. | |
|
299 | uncompressed_cache_factor = attr.ib(default=None) | |
|
300 | ||
|
301 | # The number of chunk cached | |
|
302 | uncompressed_cache_count = attr.ib(default=None) | |
|
303 | ||
|
298 | 304 | # Allow sparse reading of the revlog data |
|
299 | 305 | with_sparse_read = attr.ib(default=False) |
|
300 | 306 | # minimal density of a sparse read chunk |
@@ -396,6 +402,18 b' class _InnerRevlog:' | |||
|
396 | 402 | # 3-tuple of (node, rev, text) for a raw revision. |
|
397 | 403 | self._revisioncache = None |
|
398 | 404 | |
|
405 | # cache some uncompressed chunks | |
|
406 | # rev β uncompressed_chunk | |
|
407 | # | |
|
408 | # the max cost is dynamically updated to be proportionnal to the | |
|
409 | # size of revision we actually encounter. | |
|
410 | self._uncompressed_chunk_cache = None | |
|
411 | if self.data_config.uncompressed_cache_factor is not None: | |
|
412 | self._uncompressed_chunk_cache = util.lrucachedict( | |
|
413 | self.data_config.uncompressed_cache_count, | |
|
414 | maxcost=65536, # some arbitrary initial value | |
|
415 | ) | |
|
416 | ||
|
399 | 417 | self._delay_buffer = None |
|
400 | 418 | |
|
401 | 419 | @property |
@@ -414,6 +432,8 b' class _InnerRevlog:' | |||
|
414 | 432 | def clear_cache(self): |
|
415 | 433 | assert not self.is_delaying |
|
416 | 434 | self._revisioncache = None |
|
435 | if self._uncompressed_chunk_cache is not None: | |
|
436 | self._uncompressed_chunk_cache.clear() | |
|
417 | 437 | self._segmentfile.clear_cache() |
|
418 | 438 | self._segmentfile_sidedata.clear_cache() |
|
419 | 439 | |
@@ -865,18 +885,26 b' class _InnerRevlog:' | |||
|
865 | 885 | |
|
866 | 886 | Returns a str holding uncompressed data for the requested revision. |
|
867 | 887 | """ |
|
888 | if self._uncompressed_chunk_cache is not None: | |
|
889 | uncomp = self._uncompressed_chunk_cache.get(rev) | |
|
890 | if uncomp is not None: | |
|
891 | return uncomp | |
|
892 | ||
|
868 | 893 | compression_mode = self.index[rev][10] |
|
869 | 894 | data = self.get_segment_for_revs(rev, rev)[1] |
|
870 | 895 | if compression_mode == COMP_MODE_PLAIN: |
|
871 |
|
|
|
896 | uncomp = data | |
|
872 | 897 | elif compression_mode == COMP_MODE_DEFAULT: |
|
873 |
|
|
|
898 | uncomp = self._decompressor(data) | |
|
874 | 899 | elif compression_mode == COMP_MODE_INLINE: |
|
875 |
|
|
|
900 | uncomp = self.decompress(data) | |
|
876 | 901 | else: |
|
877 | 902 | msg = b'unknown compression mode %d' |
|
878 | 903 | msg %= compression_mode |
|
879 | 904 | raise error.RevlogError(msg) |
|
905 | if self._uncompressed_chunk_cache is not None: | |
|
906 | self._uncompressed_chunk_cache.insert(rev, uncomp, cost=len(uncomp)) | |
|
907 | return uncomp | |
|
880 | 908 | |
|
881 | 909 | def _chunks(self, revs, targetsize=None): |
|
882 | 910 | """Obtain decompressed chunks for the specified revisions. |
@@ -899,17 +927,30 b' class _InnerRevlog:' | |||
|
899 | 927 | iosize = self.index.entry_size |
|
900 | 928 | buffer = util.buffer |
|
901 | 929 | |
|
902 |
|
|
|
903 |
|
|
|
930 | fetched_revs = [] | |
|
931 | fadd = fetched_revs.append | |
|
932 | ||
|
904 | 933 | chunks = [] |
|
905 | 934 | ladd = chunks.append |
|
906 | 935 | |
|
907 | if not self.data_config.with_sparse_read: | |
|
908 |
|
|
|
936 | if self._uncompressed_chunk_cache is None: | |
|
937 | fetched_revs = revs | |
|
938 | else: | |
|
939 | for rev in revs: | |
|
940 | cached_value = self._uncompressed_chunk_cache.get(rev) | |
|
941 | if cached_value is None: | |
|
942 | fadd(rev) | |
|
943 | else: | |
|
944 | ladd((rev, cached_value)) | |
|
945 | ||
|
946 | if not fetched_revs: | |
|
947 | slicedchunks = () | |
|
948 | elif not self.data_config.with_sparse_read: | |
|
949 | slicedchunks = (fetched_revs,) | |
|
909 | 950 | else: |
|
910 | 951 | slicedchunks = deltautil.slicechunk( |
|
911 | 952 | self, |
|
912 | revs, | |
|
953 | fetched_revs, | |
|
913 | 954 | targetsize=targetsize, |
|
914 | 955 | ) |
|
915 | 956 | |
@@ -949,7 +990,10 b' class _InnerRevlog:' | |||
|
949 | 990 | msg %= comp_mode |
|
950 | 991 | raise error.RevlogError(msg) |
|
951 | 992 | ladd((rev, c)) |
|
952 | ||
|
993 | if self._uncompressed_chunk_cache is not None: | |
|
994 | self._uncompressed_chunk_cache.insert(rev, c, len(c)) | |
|
995 | ||
|
996 | chunks.sort() | |
|
953 | 997 | return [x[1] for x in chunks] |
|
954 | 998 | |
|
955 | 999 | def raw_text(self, node, rev): |
@@ -981,6 +1025,14 b' class _InnerRevlog:' | |||
|
981 | 1025 | if 0 <= rawsize: |
|
982 | 1026 | targetsize = 4 * rawsize |
|
983 | 1027 | |
|
1028 | if self._uncompressed_chunk_cache is not None: | |
|
1029 | # dynamically update the uncompressed_chunk_cache size to the | |
|
1030 | # largest revision we saw in this revlog. | |
|
1031 | factor = self.data_config.uncompressed_cache_factor | |
|
1032 | candidate_size = rawsize * factor | |
|
1033 | if candidate_size > self._uncompressed_chunk_cache.maxcost: | |
|
1034 | self._uncompressed_chunk_cache.maxcost = candidate_size | |
|
1035 | ||
|
984 | 1036 | bins = self._chunks(chain, targetsize=targetsize) |
|
985 | 1037 | if basetext is None: |
|
986 | 1038 | basetext = bytes(bins[0]) |
General Comments 0
You need to be logged in to leave comments.
Login now