##// END OF EJS Templates
revlog: add a small cache of unfiltered chunk...
marmoute -
r52001:0250e450 default
parent child Browse files
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 return data
896 uncomp = data
872 897 elif compression_mode == COMP_MODE_DEFAULT:
873 return self._decompressor(data)
898 uncomp = self._decompressor(data)
874 899 elif compression_mode == COMP_MODE_INLINE:
875 return self.decompress(data)
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 l = []
903 ladd = l.append
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 slicedchunks = (revs,)
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