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 |