Skip to content

Commit 7c39f5d

Browse files
authored
Merge pull request #106 from kgibm/issue105
[Fix #105] Add timing messages when parsing starts and finishes
2 parents 09c3fc7 + 2dc480c commit 7c39f5d

File tree

3 files changed

+158
-119
lines changed

3 files changed

+158
-119
lines changed

plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/Messages.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class Messages extends NLS
6363
public static String SnapshotFactoryImpl_Error_OpeningHeapDump;
6464
public static String SnapshotFactoryImpl_Error_ReparsingHeapDump;
6565
public static String SnapshotFactoryImpl_ErrorOpeningHeapDump;
66+
public static String SnapshotFactoryImpl_FinishOpeningDump;
6667
public static String SnapshotFactoryImpl_GCRootContextIDDoesNotMatchAddress;
6768
public static String SnapshotFactoryImpl_GCRootIDDoesNotMatchAddress;
6869
public static String SnapshotFactoryImpl_GCRootIDDoesNotMatchIndex;
@@ -85,6 +86,7 @@ public class Messages extends NLS
8586
public static String SnapshotFactoryImpl_ParsingHeapDump;
8687
public static String SnapshotFactoryImpl_ReparsingHeapDumpAsIndexOutOfDate;
8788
public static String SnapshotFactoryImpl_ReparsingHeapDumpWithOutOfDateIndex;
89+
public static String SnapshotFactoryImpl_StartOpeningDump;
8890
public static String SnapshotFactoryImpl_UnableToDeleteIndexFile;
8991
public static String SnapshotFactoryImpl_ValidatingGCRoots;
9092
public static String SnapshotFactoryImpl_ValidatingIndices;

plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/SnapshotFactoryImpl.java

Lines changed: 154 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
import java.nio.channels.OverlappingFileLockException;
2828
import java.nio.charset.StandardCharsets;
2929
import java.nio.file.StandardOpenOption;
30+
import java.text.DecimalFormat;
31+
import java.time.Duration;
32+
import java.time.ZonedDateTime;
33+
import java.time.format.DateTimeFormatter;
3034
import java.util.ArrayList;
3135
import java.util.Date;
3236
import java.util.HashMap;
@@ -82,158 +86,189 @@ public SnapshotEntry(int usageCount, ISnapshot snapshot)
8286

8387
public ISnapshot openSnapshot(File file, Map<String, String> args, IProgressListener listener) throws SnapshotException
8488
{
85-
ISnapshot answer = null;
89+
ZonedDateTime start = ZonedDateTime.now();
90+
listener.sendUserMessage(
91+
Severity.INFO, MessageUtil.format(Messages.SnapshotFactoryImpl_StartOpeningDump,
92+
file.getAbsolutePath(), DateTimeFormatter.ISO_ZONED_DATE_TIME.format(start)),
93+
null);
8694

87-
// lookup in cache
88-
SnapshotEntry entry = snapshotCache.get(file);
89-
if (entry != null)
95+
try
9096
{
91-
answer = entry.snapshot.get();
97+
ISnapshot answer = null;
9298

93-
if (answer != null)
99+
// lookup in cache
100+
SnapshotEntry entry = snapshotCache.get(file);
101+
if (entry != null)
94102
{
95-
entry.usageCount++;
96-
return answer;
103+
answer = entry.snapshot.get();
104+
105+
if (answer != null)
106+
{
107+
entry.usageCount++;
108+
return answer;
109+
}
97110
}
98-
}
99111

100-
String name = file.getName();
112+
String name = file.getName();
101113

102-
/*
103-
* Perhaps there are extensions with dots, e.g. .phd.gz or .hprof.gz,
104-
* so this code ensures the whole extension is removed.
105-
*/
106-
IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
107-
IContentType javaheapdump = contentTypeManager.getContentType("org.eclipse.mat.JavaHeapDump"); //$NON-NLS-1$
108-
List<IContentType>listtypes = new ArrayList<IContentType>();
109-
if (javaheapdump != null)
110-
{
111-
String n1 = name;
112-
IContentType types[];
113-
try (FileInputStream fis = new FileInputStream(file))
114-
{
115-
types = contentTypeManager.findContentTypesFor(fis, file.getPath());
116-
if (types.length == 0)
114+
/*
115+
* Perhaps there are extensions with dots, e.g. .phd.gz or
116+
* .hprof.gz, so this code ensures the whole extension is removed.
117+
*/
118+
IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
119+
IContentType javaheapdump = contentTypeManager.getContentType("org.eclipse.mat.JavaHeapDump"); //$NON-NLS-1$
120+
List<IContentType> listtypes = new ArrayList<IContentType>();
121+
if (javaheapdump != null)
122+
{
123+
String n1 = name;
124+
IContentType types[];
125+
try (FileInputStream fis = new FileInputStream(file))
117126
{
118-
try (FileInputStream fis2 = new FileInputStream(file))
127+
types = contentTypeManager.findContentTypesFor(fis, file.getPath());
128+
if (types.length == 0)
119129
{
120-
types = contentTypeManager.findContentTypesFor(fis2, null);
130+
try (FileInputStream fis2 = new FileInputStream(file))
131+
{
132+
types = contentTypeManager.findContentTypesFor(fis2, null);
133+
}
121134
}
122135
}
123-
}
124-
catch (IOException e)
125-
{
126-
// Ignore, try using file name alone
127-
types = contentTypeManager.findContentTypesFor(file.getPath());
128-
}
129-
for (IContentType tp : types)
130-
{
131-
if (tp.isKindOf(javaheapdump))
136+
catch (IOException e)
132137
{
133-
// See if this content description is based on the file contents
134-
IContentDescription cd1, cd2;
135-
try (FileInputStream fis = new FileInputStream(file))
136-
{
137-
// Succeeds if based on context
138-
cd1 = tp.getDescriptionFor(fis, IContentDescription.ALL);
139-
}
140-
catch (IOException e)
141-
{
142-
cd1 = null;
143-
}
144-
try (InputStream sr = new ByteArrayInputStream(new byte[10]))
145-
{
146-
// Succeeds if generic type without content checking
147-
cd2 = tp.getDescriptionFor(sr, IContentDescription.ALL);
148-
}
149-
catch (IOException e)
150-
{
151-
cd2 = null;
152-
}
153-
if (cd1 != null && cd2 == null)
138+
// Ignore, try using file name alone
139+
types = contentTypeManager.findContentTypesFor(file.getPath());
140+
}
141+
for (IContentType tp : types)
142+
{
143+
if (tp.isKindOf(javaheapdump))
154144
{
155-
listtypes.add(tp);
156-
for (String ext: tp.getFileSpecs(IContentType.FILE_EXTENSION_SPEC))
145+
// See if this content description is based on the file
146+
// contents
147+
IContentDescription cd1, cd2;
148+
try (FileInputStream fis = new FileInputStream(file))
149+
{
150+
// Succeeds if based on context
151+
cd1 = tp.getDescriptionFor(fis, IContentDescription.ALL);
152+
}
153+
catch (IOException e)
154+
{
155+
cd1 = null;
156+
}
157+
try (InputStream sr = new ByteArrayInputStream(new byte[10]))
158+
{
159+
// Succeeds if generic type without content checking
160+
cd2 = tp.getDescriptionFor(sr, IContentDescription.ALL);
161+
}
162+
catch (IOException e)
157163
{
158-
// Does extension itself contains a dot, and matches this file ?
159-
if (ext.indexOf('.') >= 0 && name.endsWith("." + ext)) //$NON-NLS-1$
164+
cd2 = null;
165+
}
166+
if (cd1 != null && cd2 == null)
167+
{
168+
listtypes.add(tp);
169+
for (String ext : tp.getFileSpecs(IContentType.FILE_EXTENSION_SPEC))
160170
{
161-
// It has a dot, so remove
162-
n1 = name.substring(0, name.length() - ext.length());
163-
// This looks a good content type as matches with long extension.
164-
// So put it first.
165-
listtypes.remove(tp);
166-
listtypes.add(0, tp);
171+
// Does extension itself contains a dot, and
172+
// matches this file ?
173+
if (ext.indexOf('.') >= 0 && name.endsWith("." + ext)) //$NON-NLS-1$
174+
{
175+
// It has a dot, so remove
176+
n1 = name.substring(0, name.length() - ext.length());
177+
// This looks a good content type as matches
178+
// with long extension.
179+
// So put it first.
180+
listtypes.remove(tp);
181+
listtypes.add(0, tp);
182+
}
167183
}
168184
}
169185
}
170186
}
187+
name = n1;
171188
}
172-
name = n1;
173-
}
174189

175-
int p = name.lastIndexOf('.');
176-
name = p >= 0 ? name.substring(0, p + 1) : name + ".";//$NON-NLS-1$
177-
String prefix = new File(file.getParentFile(), name).getAbsolutePath();
178-
String snapshot_identifier = args.get("snapshot_identifier"); //$NON-NLS-1$
179-
if (snapshot_identifier != null)
180-
{
181-
prefix += snapshot_identifier + "."; //$NON-NLS-1$
182-
}
190+
int p = name.lastIndexOf('.');
191+
name = p >= 0 ? name.substring(0, p + 1) : name + ".";//$NON-NLS-1$
192+
String prefix = new File(file.getParentFile(), name).getAbsolutePath();
193+
String snapshot_identifier = args.get("snapshot_identifier"); //$NON-NLS-1$
194+
if (snapshot_identifier != null)
195+
{
196+
prefix += snapshot_identifier + "."; //$NON-NLS-1$
197+
}
183198

184-
try
185-
{
186-
File indexFile = new File(prefix + "index");//$NON-NLS-1$
187-
if (indexFile.exists())
199+
try
188200
{
189-
// check if hprof file is newer than index file
190-
if (file.lastModified() <= indexFile.lastModified())
191-
{
192-
answer = SnapshotImpl.readFromFile(file, prefix, listener);
193-
}
194-
else
201+
File indexFile = new File(prefix + "index");//$NON-NLS-1$
202+
if (indexFile.exists())
195203
{
196-
String message = MessageUtil.format(Messages.SnapshotFactoryImpl_ReparsingHeapDumpAsIndexOutOfDate,
197-
file.getPath(), new Date(file.lastModified()),
198-
indexFile.getPath(), new Date(indexFile.lastModified()));
199-
listener.sendUserMessage(Severity.INFO, message, null);
200-
listener.subTask(Messages.SnapshotFactoryImpl_ReparsingHeapDumpWithOutOfDateIndex);
204+
// check if hprof file is newer than index file
205+
if (file.lastModified() <= indexFile.lastModified())
206+
{
207+
answer = SnapshotImpl.readFromFile(file, prefix, listener);
208+
}
209+
else
210+
{
211+
String message = MessageUtil.format(
212+
Messages.SnapshotFactoryImpl_ReparsingHeapDumpAsIndexOutOfDate, file.getPath(),
213+
new Date(file.lastModified()), indexFile.getPath(),
214+
new Date(indexFile.lastModified()));
215+
listener.sendUserMessage(Severity.INFO, message, null);
216+
listener.subTask(Messages.SnapshotFactoryImpl_ReparsingHeapDumpWithOutOfDateIndex);
217+
}
201218
}
202219
}
203-
}
204-
catch (IOException ignore_and_reparse)
205-
{
206-
String text = ignore_and_reparse.getMessage() != null ? ignore_and_reparse.getMessage()
207-
: ignore_and_reparse.getClass().getName();
208-
String message = MessageUtil.format(Messages.SnapshotFactoryImpl_Error_ReparsingHeapDump, text);
209-
listener.sendUserMessage(Severity.WARNING, message, ignore_and_reparse);
210-
listener.subTask(message);
211-
}
212-
213-
if (answer == null)
214-
{
215-
File lockFile = new File(prefix + "lock.index"); //$NON-NLS-1$
216-
/*
217-
* For autocloseable, the closeable object will be closed
218-
* when parsing is done. This will release the lock and
219-
* delete the lock file.
220-
*/
221-
try (Closeable ac = lockParse(file, lockFile, listener))
220+
catch (IOException ignore_and_reparse)
222221
{
223-
deleteIndexFiles(file, prefix, lockFile, listener);
224-
answer = parse(file, prefix, args, listtypes, listener);
222+
String text = ignore_and_reparse.getMessage() != null ? ignore_and_reparse.getMessage()
223+
: ignore_and_reparse.getClass().getName();
224+
String message = MessageUtil.format(Messages.SnapshotFactoryImpl_Error_ReparsingHeapDump, text);
225+
listener.sendUserMessage(Severity.WARNING, message, ignore_and_reparse);
226+
listener.subTask(message);
225227
}
226-
catch (IOException e)
228+
229+
if (answer == null)
227230
{
228-
throw new SnapshotException(e);
231+
File lockFile = new File(prefix + "lock.index"); //$NON-NLS-1$
232+
/*
233+
* For autocloseable, the closeable object will be closed when
234+
* parsing is done. This will release the lock and delete the
235+
* lock file.
236+
*/
237+
try (Closeable ac = lockParse(file, lockFile, listener))
238+
{
239+
deleteIndexFiles(file, prefix, lockFile, listener);
240+
answer = parse(file, prefix, args, listtypes, listener);
241+
}
242+
catch (IOException e)
243+
{
244+
throw new SnapshotException(e);
245+
}
229246
}
230-
}
231247

232-
entry = new SnapshotEntry(1, answer);
248+
entry = new SnapshotEntry(1, answer);
233249

234-
snapshotCache.put(file, entry);
250+
snapshotCache.put(file, entry);
235251

236-
return answer;
252+
return answer;
253+
}
254+
finally
255+
{
256+
ZonedDateTime end = ZonedDateTime.now();
257+
Duration duration = Duration.between(start, end);
258+
// ISO8601 format, e.g. PT10H30M182S
259+
String humanDuration = duration.toString().substring(2) /*
260+
* remove
261+
* leading
262+
* PT
263+
*/
264+
.replaceAll("([HMS])", "$1 ").toLowerCase().trim();
265+
double durationSeconds = (double) duration.toMillis() / 1000D;
266+
listener.sendUserMessage(Severity.INFO,
267+
MessageUtil.format(Messages.SnapshotFactoryImpl_FinishOpeningDump,
268+
new DecimalFormat("#,###.00").format(durationSeconds), humanDuration,
269+
DateTimeFormatter.ISO_ZONED_DATE_TIME.format(end)),
270+
null);
271+
}
237272
}
238273

239274
/**

plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/messages.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ SnapshotFactoryImpl_ClassIndexNotEqualClassObjectID=Class index {0} address {1}
6666
SnapshotFactoryImpl_ClassIndexAddressTypeIDNotEqualClassImplClassId=Class index {0} address {1} class id1 {2} different from ClassImpl class id {3} name {4}
6767
SnapshotFactoryImpl_ClassIndexAddressNoLoaderID=Class index {0} address {1} clsId {2} no loader id {3} address {4} class name {5}
6868
SnapshotFactoryImpl_ConcurrentParsingError=Concurrent parsing error, lock file: {0} reason: {1}
69+
SnapshotFactoryImpl_FinishOpeningDump=Finished opening dump in {0} seconds ({1}) at {2}
6970
SnapshotFactoryImpl_ObjectsFoundButClassesHadObjectsAndClassesInTotal={0} objects found but {1} classes had {2} objects and class objects in total
7071
SnapshotFactoryImpl_GCRootContextIDDoesNotMatchAddress=GC root info object id {0} context id {1} does not match address 0x{2}
7172
SnapshotFactoryImpl_GCRootIDOutOfRange=GC root id {0} out of range [0,{1})
@@ -79,6 +80,7 @@ SnapshotFactoryImpl_NoOutbounds=No outbounds for index {0} address {1} type {2}
7980
SnapshotFactoryImpl_ObjDescClass=class {0}
8081
SnapshotFactoryImpl_ObjDescObjType={0} {1}
8182
SnapshotFactoryImpl_ObjDescObjTypeAddress=object type address {0}
83+
SnapshotFactoryImpl_StartOpeningDump=Started opening dump {0} at {1}
8284
SnapshotFactoryImpl_UnableToDeleteIndexFile=Unable to delete index file {0}
8385
SnapshotFactoryImpl_ValidatingGCRoots=Validating GC roots
8486
SnapshotFactoryImpl_ValidatingIndices=Validating indices

0 commit comments

Comments
 (0)