Mercurial > hg4j
diff test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java @ 326:d42a45a2c9d6
Alternative tag collection approach for a file history
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 04 Oct 2011 06:28:01 +0200 |
parents | 283b294d1079 |
children | 694ebabb5cb3 |
line wrap: on
line diff
--- a/test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java Mon Oct 03 06:54:43 2011 +0200 +++ b/test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java Tue Oct 04 06:28:01 2011 +0200 @@ -17,15 +17,15 @@ import org.tmatesoft.hg.core.HgException; import org.tmatesoft.hg.core.HgLogCommand; import org.tmatesoft.hg.core.Nodeid; -import org.tmatesoft.hg.internal.ArrayHelper; +import org.tmatesoft.hg.internal.IntMap; import org.tmatesoft.hg.repo.HgChangelog; +import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.repo.HgDataFile; import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgManifest; +import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.repo.HgTags; -import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; -import org.tmatesoft.hg.repo.HgManifest.Flags; import org.tmatesoft.hg.repo.HgTags.TagInfo; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.Path; @@ -40,11 +40,11 @@ public static void main(String[] args) throws Exception { MapTagsToFileRevisions m = new MapTagsToFileRevisions(); System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); -// m.collectTagsPerFile(); + m.collectTagsPerFile(); // m.manifestWalk(); // m.changelogWalk(); // m.revisionMap(); - m.buildFile2ChangelogRevisionMap(); +// m.buildFile2ChangelogRevisionMap(); m = null; System.gc(); System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); @@ -200,6 +200,30 @@ System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start); System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); } + + private int[] collectLocalTagRevisions(HgChangelog.RevisionMap clogrmap, TagInfo[] allTags, IntMap<List<TagInfo>> tagLocalRev2TagInfo) { + int[] tagLocalRevs = new int[allTags.length]; + int x = 0; + for (int i = 0; i < allTags.length; i++) { + final Nodeid tagRevision = allTags[i].revision(); + final int tagLocalRev = clogrmap.localRevision(tagRevision); + if (tagLocalRev != HgRepository.BAD_REVISION) { + tagLocalRevs[x++] = tagLocalRev; + List<TagInfo> tagsAssociatedWithRevision = tagLocalRev2TagInfo.get(tagLocalRev); + if (tagsAssociatedWithRevision == null) { + tagLocalRev2TagInfo.put(tagLocalRev, tagsAssociatedWithRevision = new LinkedList<TagInfo>()); + } + tagsAssociatedWithRevision.add(allTags[i]); + } + } + if (x != allTags.length) { + // some tags were removed (recorded Nodeid.NULL tagname) + int[] copy = new int[x]; + System.arraycopy(tagLocalRevs, 0, copy, 0, x); + tagLocalRevs = copy; + } + return tagLocalRevs; + } private void collectTagsPerFile() throws HgException, CancelledException { final long start = System.currentTimeMillis(); @@ -210,33 +234,36 @@ // final TagInfo[] allTags = new TagInfo[tags.getTags().size()]; tags.getTags().values().toArray(allTags); + // effective translation of changeset revisions to their local indexes + final HgChangelog.RevisionMap clogrmap = repository.getChangelog().new RevisionMap().init(); + // map to look up tag by changeset local number + final IntMap<List<TagInfo>> tagLocalRev2TagInfo = new IntMap<List<TagInfo>>(allTags.length); + System.out.printf("Collecting manifests for %d tags\n", allTags.length); + final int[] tagLocalRevs = collectLocalTagRevisions(clogrmap, allTags, tagLocalRev2TagInfo); + System.out.printf("Prepared tag revisions to analyze: %d ms\n", System.currentTimeMillis() - start); + + final Path targetPath = Path.create("README"); + // + collectTagsPerFile_Approach_1(clogrmap, tagLocalRevs, allTags, targetPath); + System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start); + + System.out.println("\nApproach 2"); + collectTagsPerFile_Approach_2(repository, tagLocalRevs, tagLocalRev2TagInfo, allTags, targetPath); + } + + // Approach 1. Build map with all files, their revisions and corresponding tags + // + private void collectTagsPerFile_Approach_1(final HgChangelog.RevisionMap clogrmap, final int[] tagLocalRevs, final TagInfo[] allTags, Path targetPath) { + HgRepository repository = clogrmap.getRepo(); + final long start = System.currentTimeMillis(); // file2rev2tag value is array of revisions, always of allTags.length. Revision index in the array // is index of corresponding TagInfo in allTags; final Map<Path, Nodeid[]> file2rev2tag = new HashMap<Path, Nodeid[]>(); - System.out.printf("Collecting manifests for %d tags\n", allTags.length); - // effective translation of changeset revisions to their local indexes - final HgChangelog.RevisionMap clogrmap = repository.getChangelog().new RevisionMap().init(); - int[] tagLocalRevs = new int[allTags.length]; - int x = 0; - for (int i = 0; i < allTags.length; i++) { - final Nodeid tagRevision = allTags[i].revision(); - final int tagLocalRev = clogrmap.localRevision(tagRevision); - if (tagLocalRev != HgRepository.BAD_REVISION) { - tagLocalRevs[x++] = tagLocalRev; - } - } - if (x != allTags.length) { - // some tags were removed (recorded Nodeid.NULL tagname) - int[] copy = new int[x]; - System.arraycopy(tagLocalRevs, 0, copy, 0, x); - tagLocalRevs = copy; - } - System.out.printf("Prepared tag revisions to analyze: %d ms\n", System.currentTimeMillis() - start); - // repository.getManifest().walk(new HgManifest.Inspector2() { private int[] tagIndexAtRev = new int[4]; // it's unlikely there would be a lot of tags associated with a given cset public boolean begin(int mainfestRevision, Nodeid nid, int changelogRevision) { + // may do better here using tagLocalRev2TagInfo, but need to change a lot, too lazy now Nodeid cset = clogrmap.revision(changelogRevision); Arrays.fill(tagIndexAtRev, -1); for (int i = 0, x = 0; i < allTags.length; i++) { @@ -286,7 +313,6 @@ System.out.printf("Cache built: %d ms\n", System.currentTimeMillis() - start); // // look up specific file. This part is fast. - final Path targetPath = Path.create("README"); HgDataFile fileNode = repository.getFileNode(targetPath); final Nodeid[] allTagsOfTheFile = file2rev2tag.get(targetPath); // TODO if fileNode.isCopy, repeat for each getCopySourceName() @@ -301,7 +327,41 @@ } System.out.printf("%3d%7d%s\n", localFileRev, changesetLocalRev, associatedTags); } - System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start); + } + + private void collectTagsPerFile_Approach_2(HgRepository repository, final int[] tagLocalRevs, final IntMap<List<TagInfo>> tagLocalRev2TagInfo, TagInfo[] allTags, Path targetPath) { + // + // Approach 2. No all-file map. Collect file revisions recorded at the time of tagging, + // then for each file revision check if it is among those above, and if yes, take corresponding tags + HgDataFile fileNode = repository.getFileNode(targetPath); + final long start2 = System.nanoTime(); + final int lastRev = fileNode.getLastRevision(); + final Map<Integer, Nodeid> fileRevisionAtTagRevision = repository.getManifest().getFileRevisions(targetPath, tagLocalRevs); + final long start2a = System.nanoTime(); + fileNode.walk(0, lastRev, new HgDataFile.RevisionInspector() { + + public void next(int localFileRev, Nodeid fileRevision, int linkedRevision) { + int changesetLocalRev = linkedRevision; + List<String> associatedTags = new LinkedList<String>(); + for (int taggetRevision : tagLocalRevs) { + // current file revision can't appear in tags that point to earlier changelog revisions (they got own file revision) + if (taggetRevision >= changesetLocalRev) { + // z points to some changeset with tag + Nodeid wasKnownAs = fileRevisionAtTagRevision.get(taggetRevision); + if (wasKnownAs.equals(fileRevision)) { + // has tag associated with changeset at index z + List<TagInfo> tagsAtRev = tagLocalRev2TagInfo.get(taggetRevision); + assert tagsAtRev != null; + for (TagInfo ti : tagsAtRev) { + associatedTags.add(ti.name()); + } + } + } + } + System.out.printf("%3d%7d%s\n", localFileRev, changesetLocalRev, associatedTags); + } + }); + System.out.printf("Alternative total time: %d ms, of that init: %d ms\n", (System.nanoTime() - start2)/1000000, (start2a-start2)/1000000); System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); }