Show More
@@ -621,6 +621,74 b' class remotebranchcache(branchcache):' | |||||
621 | _rbccloseflag = 0x80000000 |
|
621 | _rbccloseflag = 0x80000000 | |
622 |
|
622 | |||
623 |
|
623 | |||
|
624 | class rbcrevs: | |||
|
625 | """a byte string consisting of an immutable prefix followed by a mutable suffix""" | |||
|
626 | ||||
|
627 | def __init__(self, revs): | |||
|
628 | self._prefix = revs | |||
|
629 | self._rest = bytearray() | |||
|
630 | ||||
|
631 | def __len__(self): | |||
|
632 | return len(self._prefix) + len(self._rest) | |||
|
633 | ||||
|
634 | def unpack_record(self, rbcrevidx): | |||
|
635 | if rbcrevidx < len(self._prefix): | |||
|
636 | return unpack_from(_rbcrecfmt, util.buffer(self._prefix), rbcrevidx) | |||
|
637 | else: | |||
|
638 | return unpack_from( | |||
|
639 | _rbcrecfmt, | |||
|
640 | util.buffer(self._rest), | |||
|
641 | rbcrevidx - len(self._prefix), | |||
|
642 | ) | |||
|
643 | ||||
|
644 | def make_mutable(self): | |||
|
645 | if len(self._prefix) > 0: | |||
|
646 | entirety = bytearray() | |||
|
647 | entirety[:] = self._prefix | |||
|
648 | entirety.extend(self._rest) | |||
|
649 | self._rest = entirety | |||
|
650 | self._prefix = bytearray() | |||
|
651 | ||||
|
652 | def truncate(self, pos): | |||
|
653 | self.make_mutable() | |||
|
654 | del self._rest[pos:] | |||
|
655 | ||||
|
656 | def pack_into(self, rbcrevidx, node, branchidx): | |||
|
657 | if rbcrevidx < len(self._prefix): | |||
|
658 | self.make_mutable() | |||
|
659 | buf = self._rest | |||
|
660 | start_offset = rbcrevidx - len(self._prefix) | |||
|
661 | end_offset = start_offset + _rbcrecsize | |||
|
662 | ||||
|
663 | if len(self._rest) < end_offset: | |||
|
664 | # bytearray doesn't allocate extra space at least in Python 3.7. | |||
|
665 | # When multiple changesets are added in a row, precise resize would | |||
|
666 | # result in quadratic complexity. Overallocate to compensate by | |||
|
667 | # using the classic doubling technique for dynamic arrays instead. | |||
|
668 | # If there was a gap in the map before, less space will be reserved. | |||
|
669 | self._rest.extend(b'\0' * end_offset) | |||
|
670 | return pack_into( | |||
|
671 | _rbcrecfmt, | |||
|
672 | buf, | |||
|
673 | start_offset, | |||
|
674 | node, | |||
|
675 | branchidx, | |||
|
676 | ) | |||
|
677 | ||||
|
678 | def extend(self, extension): | |||
|
679 | return self._rest.extend(extension) | |||
|
680 | ||||
|
681 | def slice(self, begin, end): | |||
|
682 | if begin < len(self._prefix): | |||
|
683 | acc = bytearray() | |||
|
684 | acc[:] = self._prefix[begin:end] | |||
|
685 | acc.extend( | |||
|
686 | self._rest[begin - len(self._prefix) : end - len(self._prefix)] | |||
|
687 | ) | |||
|
688 | return acc | |||
|
689 | return self._rest[begin - len(self._prefix) : end - len(self._prefix)] | |||
|
690 | ||||
|
691 | ||||
624 | class revbranchcache: |
|
692 | class revbranchcache: | |
625 | """Persistent cache, mapping from revision number to branch name and close. |
|
693 | """Persistent cache, mapping from revision number to branch name and close. | |
626 | This is a low level cache, independent of filtering. |
|
694 | This is a low level cache, independent of filtering. | |
@@ -648,7 +716,7 b' class revbranchcache:' | |||||
648 | assert repo.filtername is None |
|
716 | assert repo.filtername is None | |
649 | self._repo = repo |
|
717 | self._repo = repo | |
650 | self._names = [] # branch names in local encoding with static index |
|
718 | self._names = [] # branch names in local encoding with static index | |
651 | self._rbcrevs = bytearray() |
|
719 | self._rbcrevs = rbcrevs(bytearray()) | |
652 | self._rbcsnameslen = 0 # length of names read at _rbcsnameslen |
|
720 | self._rbcsnameslen = 0 # length of names read at _rbcsnameslen | |
653 | try: |
|
721 | try: | |
654 | bndata = repo.cachevfs.read(_rbcnames) |
|
722 | bndata = repo.cachevfs.read(_rbcnames) | |
@@ -664,8 +732,12 b' class revbranchcache:' | |||||
664 |
|
732 | |||
665 | if self._names: |
|
733 | if self._names: | |
666 | try: |
|
734 | try: | |
667 | data = repo.cachevfs.read(_rbcrevs) |
|
735 | if repo.ui.configbool(b'format', b'mmap-revbranchcache'): | |
668 | self._rbcrevs[:] = data |
|
736 | with repo.cachevfs(_rbcrevs) as fp: | |
|
737 | data = util.buffer(util.mmapread(fp)) | |||
|
738 | else: | |||
|
739 | data = repo.cachevfs.read(_rbcrevs) | |||
|
740 | self._rbcrevs = rbcrevs(data) | |||
669 | except (IOError, OSError) as inst: |
|
741 | except (IOError, OSError) as inst: | |
670 | repo.ui.debug( |
|
742 | repo.ui.debug( | |
671 | b"couldn't read revision branch cache: %s\n" |
|
743 | b"couldn't read revision branch cache: %s\n" | |
@@ -685,7 +757,7 b' class revbranchcache:' | |||||
685 | del self._names[:] |
|
757 | del self._names[:] | |
686 | self._rbcnamescount = 0 |
|
758 | self._rbcnamescount = 0 | |
687 | self._rbcrevslen = len(self._repo.changelog) |
|
759 | self._rbcrevslen = len(self._repo.changelog) | |
688 | self._rbcrevs = bytearray(self._rbcrevslen * _rbcrecsize) |
|
760 | self._rbcrevs = rbcrevs(bytearray(self._rbcrevslen * _rbcrecsize)) | |
689 | util.clearcachedproperty(self, b'_namesreverse') |
|
761 | util.clearcachedproperty(self, b'_namesreverse') | |
690 |
|
762 | |||
691 | @util.propertycache |
|
763 | @util.propertycache | |
@@ -708,9 +780,7 b' class revbranchcache:' | |||||
708 |
|
780 | |||
709 | # fast path: extract data from cache, use it if node is matching |
|
781 | # fast path: extract data from cache, use it if node is matching | |
710 | reponode = changelog.node(rev)[:_rbcnodelen] |
|
782 | reponode = changelog.node(rev)[:_rbcnodelen] | |
711 |
cachenode, branchidx = unpack_ |
|
783 | cachenode, branchidx = self._rbcrevs.unpack_record(rbcrevidx) | |
712 | _rbcrecfmt, util.buffer(self._rbcrevs), rbcrevidx |
|
|||
713 | ) |
|
|||
714 | close = bool(branchidx & _rbccloseflag) |
|
784 | close = bool(branchidx & _rbccloseflag) | |
715 | if close: |
|
785 | if close: | |
716 | branchidx &= _rbcbranchidxmask |
|
786 | branchidx &= _rbcbranchidxmask | |
@@ -733,7 +803,7 b' class revbranchcache:' | |||||
733 | b"revision branch cache to revision %d\n" % rev |
|
803 | b"revision branch cache to revision %d\n" % rev | |
734 | ) |
|
804 | ) | |
735 | truncate = rbcrevidx + _rbcrecsize |
|
805 | truncate = rbcrevidx + _rbcrecsize | |
736 |
|
|
806 | self._rbcrevs.truncate(truncate) | |
737 | self._rbcrevslen = min(self._rbcrevslen, truncate) |
|
807 | self._rbcrevslen = min(self._rbcrevslen, truncate) | |
738 |
|
808 | |||
739 | # fall back to slow path and make sure it will be written to disk |
|
809 | # fall back to slow path and make sure it will be written to disk | |
@@ -782,16 +852,7 b' class revbranchcache:' | |||||
782 | if rev == nullrev: |
|
852 | if rev == nullrev: | |
783 | return |
|
853 | return | |
784 | rbcrevidx = rev * _rbcrecsize |
|
854 | rbcrevidx = rev * _rbcrecsize | |
785 | requiredsize = rbcrevidx + _rbcrecsize |
|
855 | self._rbcrevs.pack_into(rbcrevidx, node, branchidx) | |
786 | rbccur = len(self._rbcrevs) |
|
|||
787 | if rbccur < requiredsize: |
|
|||
788 | # bytearray doesn't allocate extra space at least in Python 3.7. |
|
|||
789 | # When multiple changesets are added in a row, precise resize would |
|
|||
790 | # result in quadratic complexity. Overallocate to compensate by |
|
|||
791 | # use the classic doubling technique for dynamic arrays instead. |
|
|||
792 | # If there was a gap in the map before, less space will be reserved. |
|
|||
793 | self._rbcrevs.extend(b'\0' * max(_rbcmininc, requiredsize)) |
|
|||
794 | pack_into(_rbcrecfmt, self._rbcrevs, rbcrevidx, node, branchidx) |
|
|||
795 | self._rbcrevslen = min(self._rbcrevslen, rev) |
|
856 | self._rbcrevslen = min(self._rbcrevslen, rev) | |
796 |
|
857 | |||
797 | tr = self._repo.currenttransaction() |
|
858 | tr = self._repo.currenttransaction() | |
@@ -866,5 +927,5 b' class revbranchcache:' | |||||
866 | f.seek(start) |
|
927 | f.seek(start) | |
867 | f.truncate() |
|
928 | f.truncate() | |
868 | end = revs * _rbcrecsize |
|
929 | end = revs * _rbcrecsize | |
869 |
f.write(self._rbcrevs |
|
930 | f.write(self._rbcrevs.slice(start, end)) | |
870 | self._rbcrevslen = revs |
|
931 | self._rbcrevslen = revs |
@@ -2913,3 +2913,8 b' section = "blackbox"' | |||||
2913 | name = "date-format" |
|
2913 | name = "date-format" | |
2914 | default = "" |
|
2914 | default = "" | |
2915 | in_core_extension = "blackbox" |
|
2915 | in_core_extension = "blackbox" | |
|
2916 | ||||
|
2917 | [[items]] | |||
|
2918 | section = "format" | |||
|
2919 | name = "mmap-revbranchcache" | |||
|
2920 | default = false |
@@ -1,3 +1,12 b'' | |||||
|
1 | #testcases mmap nommap | |||
|
2 | ||||
|
3 | #if mmap | |||
|
4 | $ cat <<EOF >> $HGRCPATH | |||
|
5 | > [format] | |||
|
6 | > mmap-revbranchcache=true | |||
|
7 | > EOF | |||
|
8 | #endif | |||
|
9 | ||||
1 | $ hg init a |
|
10 | $ hg init a | |
2 | $ cd a |
|
11 | $ cd a | |
3 |
|
12 | |||
@@ -921,17 +930,10 b' Test that cache files are created and gr' | |||||
921 | $ f --size --hexdump .hg/cache/rbc-* |
|
930 | $ f --size --hexdump .hg/cache/rbc-* | |
922 | .hg/cache/rbc-names-v1: size=1 |
|
931 | .hg/cache/rbc-names-v1: size=1 | |
923 | 0000: 61 |a| |
|
932 | 0000: 61 |a| | |
924 |
.hg/cache/rbc-revs-v1: size= |
|
933 | .hg/cache/rbc-revs-v1: size=48 | |
925 | 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
934 | 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | |
926 | 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
935 | 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | |
927 | 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 00 |................| |
|
936 | 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 00 |................| | |
928 | 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
|||
929 | 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
|||
930 | 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
|||
931 | 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
|||
932 | 0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
|||
933 | 0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| |
|
|||
934 | 0090: 00 00 00 00 00 00 00 00 |........| |
|
|||
935 |
|
937 | |||
936 | $ cd .. |
|
938 | $ cd .. | |
937 |
|
939 |
General Comments 0
You need to be logged in to leave comments.
Login now