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