Mercurial > hg
comparison mercurial/changegroup.py @ 41448:fa7d61f9c512
changegroup: don't try to build changelog chunks if not required
When we extend a narrow clone without ellipsis, we don't download changelog
information because that's already present with the client. However we still try
to build that chunk stream. Building that chunk stream involves calling a lookup
function and store.emitrevisions() API. The lookup function is called len(cl)
number of times.
On large repositories, where len(cl) is in millions, calling that lookup
function is not a good idea. Also it's not required to use the
store.emitrevisons() API because we already have nodes present which we can use.
This patch short-circuits state building logic if we are processing a
non-ellipsis case and changelog is not required.
This saves up ~20 seconds on our internal repo for a single extend call.
Differential Revision: https://phab.mercurial-scm.org/D5733
author | Pulkit Goyal <pulkit@yandex-team.ru> |
---|---|
date | Tue, 29 Jan 2019 16:03:52 +0300 |
parents | 73a33fe625bb |
children | 1db5ae4b0dda |
comparison
equal
deleted
inserted
replaced
41445:73a33fe625bb | 41448:fa7d61f9c512 |
---|---|
815 cl = repo.changelog | 815 cl = repo.changelog |
816 | 816 |
817 self._verbosenote(_('uncompressed size of bundle content:\n')) | 817 self._verbosenote(_('uncompressed size of bundle content:\n')) |
818 size = 0 | 818 size = 0 |
819 | 819 |
820 clstate, deltas = self._generatechangelog(cl, clnodes) | 820 clstate, deltas = self._generatechangelog(cl, clnodes, |
821 generate=changelog) | |
821 for delta in deltas: | 822 for delta in deltas: |
822 if changelog: | 823 for chunk in _revisiondeltatochunks(delta, |
823 for chunk in _revisiondeltatochunks(delta, | 824 self._builddeltaheader): |
824 self._builddeltaheader): | 825 size += len(chunk) |
825 size += len(chunk) | 826 yield chunk |
826 yield chunk | |
827 | 827 |
828 close = closechunk() | 828 close = closechunk() |
829 size += len(close) | 829 size += len(close) |
830 yield closechunk() | 830 yield closechunk() |
831 | 831 |
915 yield closechunk() | 915 yield closechunk() |
916 | 916 |
917 if clnodes: | 917 if clnodes: |
918 repo.hook('outgoing', node=hex(clnodes[0]), source=source) | 918 repo.hook('outgoing', node=hex(clnodes[0]), source=source) |
919 | 919 |
920 def _generatechangelog(self, cl, nodes): | 920 def _generatechangelog(self, cl, nodes, generate=True): |
921 """Generate data for changelog chunks. | 921 """Generate data for changelog chunks. |
922 | 922 |
923 Returns a 2-tuple of a dict containing state and an iterable of | 923 Returns a 2-tuple of a dict containing state and an iterable of |
924 byte chunks. The state will not be fully populated until the | 924 byte chunks. The state will not be fully populated until the |
925 chunk stream has been fully consumed. | 925 chunk stream has been fully consumed. |
926 | |
927 if generate is False, the state will be fully populated and no chunk | |
928 stream will be yielded | |
926 """ | 929 """ |
927 clrevorder = {} | 930 clrevorder = {} |
928 manifests = {} | 931 manifests = {} |
929 mfl = self._repo.manifestlog | 932 mfl = self._repo.manifestlog |
930 changedfiles = set() | 933 changedfiles = set() |
934 'clrevorder': clrevorder, | 937 'clrevorder': clrevorder, |
935 'manifests': manifests, | 938 'manifests': manifests, |
936 'changedfiles': changedfiles, | 939 'changedfiles': changedfiles, |
937 'clrevtomanifestrev': clrevtomanifestrev, | 940 'clrevtomanifestrev': clrevtomanifestrev, |
938 } | 941 } |
942 | |
943 if not (generate or self._ellipses): | |
944 # sort the nodes in storage order | |
945 nodes = sorted(nodes, key=cl.rev) | |
946 for node in nodes: | |
947 c = cl.changelogrevision(node) | |
948 clrevorder[node] = len(clrevorder) | |
949 # record the first changeset introducing this manifest version | |
950 manifests.setdefault(c.manifest, node) | |
951 # Record a complete list of potentially-changed files in | |
952 # this manifest. | |
953 changedfiles.update(c.files) | |
954 | |
955 return state, () | |
939 | 956 |
940 # Callback for the changelog, used to collect changed files and | 957 # Callback for the changelog, used to collect changed files and |
941 # manifest nodes. | 958 # manifest nodes. |
942 # Returns the linkrev node (identity in the changelog case). | 959 # Returns the linkrev node (identity in the changelog case). |
943 def lookupcl(x): | 960 def lookupcl(x): |