Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 266:0a2f445de774
Improve manifest parsing: reduce number of arrays instantiated for Nodeid
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Fri, 19 Aug 2011 04:59:32 +0200 |
| parents | 6bb5e7ed051a |
| children | ec921ef0628e |
comparison
equal
deleted
inserted
replaced
| 265:3dd953c65619 | 266:0a2f445de774 |
|---|---|
| 24 import java.util.Arrays; | 24 import java.util.Arrays; |
| 25 | 25 |
| 26 import org.tmatesoft.hg.core.HgBadStateException; | 26 import org.tmatesoft.hg.core.HgBadStateException; |
| 27 import org.tmatesoft.hg.core.Nodeid; | 27 import org.tmatesoft.hg.core.Nodeid; |
| 28 import org.tmatesoft.hg.internal.DataAccess; | 28 import org.tmatesoft.hg.internal.DataAccess; |
| 29 import org.tmatesoft.hg.internal.DigestHelper; | |
| 29 import org.tmatesoft.hg.internal.Experimental; | 30 import org.tmatesoft.hg.internal.Experimental; |
| 30 import org.tmatesoft.hg.internal.Lifecycle; | 31 import org.tmatesoft.hg.internal.Lifecycle; |
| 31 import org.tmatesoft.hg.internal.Pool; | 32 import org.tmatesoft.hg.internal.Pool; |
| 32 import org.tmatesoft.hg.internal.Pool2; | 33 import org.tmatesoft.hg.internal.Pool2; |
| 33 import org.tmatesoft.hg.internal.RevlogStream; | 34 import org.tmatesoft.hg.internal.RevlogStream; |
| 148 boolean begin(int mainfestRevision, Nodeid nid, int changelogRevision); | 149 boolean begin(int mainfestRevision, Nodeid nid, int changelogRevision); |
| 149 boolean next(Nodeid nid, String fname, String flags); | 150 boolean next(Nodeid nid, String fname, String flags); |
| 150 boolean end(int manifestRevision); | 151 boolean end(int manifestRevision); |
| 151 } | 152 } |
| 152 | 153 |
| 153 private static class ManifestParser implements RevlogStream.Inspector/*, Lifecycle*/ { | 154 private static class ManifestParser implements RevlogStream.Inspector/*, Lifecycle */{ |
| 154 private boolean gtg = true; // good to go | 155 private boolean gtg = true; // good to go |
| 155 private final Inspector inspector; | 156 private final Inspector inspector; |
| 156 private Pool2<Nodeid> nodeidPool, thisRevPool; | 157 private Pool2<Nodeid> nodeidPool, thisRevPool; |
| 157 private final Pool2<String> fnamePool; | 158 private final Pool2<String> fnamePool; |
| 158 private final Pool<String> flagsPool; | 159 private final Pool<String> flagsPool; |
| 160 private final byte[] nodeidAsciiConvertBuffer = new byte[40]; | |
| 161 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool | |
| 159 | 162 |
| 160 public ManifestParser(Inspector delegate) { | 163 public ManifestParser(Inspector delegate) { |
| 161 assert delegate != null; | 164 assert delegate != null; |
| 162 inspector = delegate; | 165 inspector = delegate; |
| 163 nodeidPool = new Pool2<Nodeid>(); | 166 nodeidPool = new Pool2<Nodeid>(); |
| 173 try { | 176 try { |
| 174 gtg = gtg && inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision); | 177 gtg = gtg && inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision); |
| 175 String fname = null; | 178 String fname = null; |
| 176 String flags = null; | 179 String flags = null; |
| 177 Nodeid nid = null; | 180 Nodeid nid = null; |
| 178 final char[] nodeidConvertCache = new char[40]; | |
| 179 String data = new String(da.byteArray()); | 181 String data = new String(da.byteArray()); |
| 180 final int dataLen = data.length(); // due to byte->char conversion, may be different | 182 final int dataLen = data.length(); // due to byte->char conversion, may be different |
| 181 for (int x = 0; gtg && x < dataLen; x++) { | 183 for (int x = 0; gtg && x < dataLen; x++) { |
| 182 int start = x; | 184 int start = x; |
| 183 x = data.indexOf('\n', x+1); | 185 x = data.indexOf('\n', x+1); |
| 191 } else { | 193 } else { |
| 192 fnamePool.record(fname = new String(fname)); | 194 fnamePool.record(fname = new String(fname)); |
| 193 } | 195 } |
| 194 z++; // cursor at first char of nodeid | 196 z++; // cursor at first char of nodeid |
| 195 int nodeidLen = x-z < 40 ? x-z : 40; // if x-z > 40, there are flags | 197 int nodeidLen = x-z < 40 ? x-z : 40; // if x-z > 40, there are flags |
| 196 data.getChars(z, z+nodeidLen, nodeidConvertCache, 0); | 198 for (int k = 0; k < nodeidLen; k++) { |
| 197 nid = nodeidPool.unify(Nodeid.fromAscii(nodeidConvertCache, 0, nodeidLen)); | 199 // intentionally didn't clear array as it shall be of length 40 (Nodeid.fromAscii won't stand anything but 40) |
| 200 nodeidAsciiConvertBuffer[k] = (byte) data.charAt(z+k); | |
| 201 } | |
| 202 DigestHelper.ascii2bin(nodeidAsciiConvertBuffer, 0, nodeidLen, nodeidLookupBuffer); | |
| 203 nid = new Nodeid(nodeidLookupBuffer, false); // this Nodeid is for pool lookup only, mock object | |
| 204 Nodeid cached = nodeidPool.unify(nid); | |
| 205 if (cached == nid) { | |
| 206 // buffer now belongs to the cached nodeid | |
| 207 nodeidLookupBuffer = new byte[20]; | |
| 208 } else { | |
| 209 nid = cached; // use existing version, discard the lookup object | |
| 210 } | |
| 198 thisRevPool.record(nid); // memorize revision for the next iteration. | 211 thisRevPool.record(nid); // memorize revision for the next iteration. |
| 199 if (x-z > 40) { | 212 if (x-z > 40) { |
| 200 // 'x' and 'l' for executable bits and symlinks? | 213 // 'x' and 'l' for executable bits and symlinks? |
| 201 // hg --debug manifest shows 644 for each regular file in my repo | 214 // hg --debug manifest shows 644 for each regular file in my repo |
| 202 // for cpython repo, there are 755 in hg --debug output when 'x' flag is present | 215 // for cpython repo, there are 755 in hg --debug output when 'x' flag is present |
