Optimization, PK3: approximately 2x performance increase during background resource loading (~7 seconds vs ~16 seconds in r2083, tested on Enjay's Genetech MAP01).

Fixed, PK7: fixed a potential crash when using several PK7 resources with overlapping files.
This commit is contained in:
MaxED 2014-10-15 08:36:17 +00:00
parent 91152ee69e
commit eb9781b339
3 changed files with 95 additions and 54 deletions

View file

@ -642,6 +642,12 @@ namespace CodeImp.DoomBuilder.Data
// Timing // Timing
if(loadfinishtime == 0) if(loadfinishtime == 0)
{ {
//mxd. Release PK3 files
foreach (DataReader reader in containers)
{
if (reader is PK3Reader) (reader as PK3Reader).BathMode = false;
}
loadfinishtime = Clock.CurrentTime; loadfinishtime = Clock.CurrentTime;
float deltatimesec = (loadfinishtime - loadstarttime) / 1000.0f; float deltatimesec = (loadfinishtime - loadstarttime) / 1000.0f;
General.WriteLogLine("Resources loading took " + deltatimesec.ToString("########0.00") + " seconds"); General.WriteLogLine("Resources loading took " + deltatimesec.ToString("########0.00") + " seconds");
@ -1408,7 +1414,7 @@ namespace CodeImp.DoomBuilder.Data
} }
if (actors.Count == 0) if (actors.Count == 0)
General.ErrorLogger.Add(ErrorType.Warning, "Warning: unable to find any DECORATE actors definition!"); General.ErrorLogger.Add(ErrorType.Warning, "Warning: unable to find any DECORATE actor definitions!");
return actors; return actors;
} }

View file

@ -74,7 +74,7 @@ namespace CodeImp.DoomBuilder.Data
{ {
// Load file data // Load file data
if(bitmap != null) bitmap.Dispose(); bitmap = null; if(bitmap != null) bitmap.Dispose(); bitmap = null;
MemoryStream filedata = datareader.ExtractFile(fullName); //mxd MemoryStream filedata = datareader.LoadFile(fullName); //mxd
// Get a reader for the data // Get a reader for the data
IImageReader reader = ImageDataFormat.GetImageReader(filedata, probableformat, General.Map.Data.Palette); IImageReader reader = ImageDataFormat.GetImageReader(filedata, probableformat, General.Map.Data.Palette);

View file

@ -32,9 +32,17 @@ namespace CodeImp.DoomBuilder.Data
{ {
#region ================== Variables #region ================== Variables
private DirectoryFilesList files; private readonly DirectoryFilesList files;
private ArchiveType archiveType; //mxd private IArchive archive; //mxd
private static Dictionary<string, byte[]> sevenZipEntries; //mxd private readonly ArchiveType archivetype; //mxd
private readonly Dictionary<string, byte[]> sevenzipentries; //mxd
private bool bathmode = true; //mxd
#endregion
#region ================== Properties (mxd)
public bool BathMode { get { return bathmode; } set { bathmode = value; UpdateArchive(bathmode); } }
#endregion #endregion
@ -51,34 +59,37 @@ namespace CodeImp.DoomBuilder.Data
// Make list of all files // Make list of all files
List<DirectoryFileEntry> fileentries = new List<DirectoryFileEntry>(); List<DirectoryFileEntry> fileentries = new List<DirectoryFileEntry>();
//mxd // Create archive
IArchive archive = ArchiveFactory.Open(location.location); archive = ArchiveFactory.Open(location.location, Options.KeepStreamsOpen);
archiveType = archive.Type; archivetype = archive.Type;
if (archive.Type == ArchiveType.SevenZip) { //random access of 7z archives works TERRIBLY slow in SharpCompress // Random access of 7z archives works TERRIBLY slow in SharpCompress
sevenZipEntries = new Dictionary<string, byte[]>(StringComparer.Ordinal); if(archivetype == ArchiveType.SevenZip)
{
sevenzipentries = new Dictionary<string, byte[]>(StringComparer.Ordinal);
IReader reader = archive.ExtractAllEntries(); IReader reader = archive.ExtractAllEntries();
while (reader.MoveToNextEntry()) { while(reader.MoveToNextEntry())
if (!reader.Entry.IsDirectory) { {
if(reader.Entry.IsDirectory) continue;
MemoryStream s = new MemoryStream(); MemoryStream s = new MemoryStream();
reader.WriteEntryTo(s); reader.WriteEntryTo(s);
sevenZipEntries.Add(reader.Entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), s.ToArray()); sevenzipentries.Add(reader.Entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), s.ToArray());
fileentries.Add(new DirectoryFileEntry(reader.Entry.FilePath)); fileentries.Add(new DirectoryFileEntry(reader.Entry.FilePath));
} }
}
//archive.Dispose();
//archive = null;
} else {
foreach (IEntry entry in archive.Entries) {
if (!entry.IsDirectory)
fileentries.Add(new DirectoryFileEntry(entry.FilePath));
}
}
archive.Dispose(); archive.Dispose();
archive = null; archive = null;
}
else
{
foreach(IArchiveEntry entry in archive.Entries)
{
if(entry.IsDirectory) continue;
fileentries.Add(new DirectoryFileEntry(entry.FilePath));
}
}
// Make files list // Make files list
files = new DirectoryFilesList(fileentries); files = new DirectoryFilesList(fileentries);
@ -97,13 +108,35 @@ namespace CodeImp.DoomBuilder.Data
if(!isdisposed) if(!isdisposed)
{ {
General.WriteLogLine("Closing " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource '" + location.location + "'"); General.WriteLogLine("Closing " + Path.GetExtension(location.location).ToUpper().Replace(".", "") + " resource '" + location.location + "'");
//if(archive != null) archive.Dispose(); //mxd
//mxd
if(archive != null)
{
archive.Dispose();
archive = null;
}
// Done // Done
base.Dispose(); base.Dispose();
} }
} }
//mxd
private void UpdateArchive(bool enable)
{
if(archivetype == ArchiveType.SevenZip) return;
if (enable && archive == null)
{
archive = ArchiveFactory.Open(location.location, Options.KeepStreamsOpen);
}
else if(!enable && !bathmode && archive != null)
{
archive.Dispose();
archive = null;
}
}
#endregion #endregion
#region ================== Textures #region ================== Textures
@ -349,7 +382,7 @@ namespace CodeImp.DoomBuilder.Data
{ {
string title = Path.GetFileNameWithoutExtension(beginswith); string title = Path.GetFileNameWithoutExtension(beginswith);
string ext = Path.GetExtension(beginswith); string ext = Path.GetExtension(beginswith);
if(ext.Length > 1) ext = ext.Substring(1); else ext = ""; ext = (!string.IsNullOrEmpty(ext) && ext.Length > 1 ? ext.Substring(1) : "");
return files.GetFirstFile(path, title, subfolders, ext); return files.GetFirstFile(path, title, subfolders, ext);
} }
@ -359,31 +392,39 @@ namespace CodeImp.DoomBuilder.Data
{ {
MemoryStream filedata = null; MemoryStream filedata = null;
//mxd //mxd. This works waaaaaay faster with 7z archive
if (archiveType == ArchiveType.SevenZip) { //this works waaaaaay faster with 7z archive if (archivetype == ArchiveType.SevenZip)
if (sevenZipEntries.ContainsKey(filename)) {
filedata = new MemoryStream(sevenZipEntries[filename]); if (sevenzipentries.ContainsKey(filename))
} else { filedata = new MemoryStream(sevenzipentries[filename]);
IArchive archive = ArchiveFactory.Open(location.location); }
else
{
UpdateArchive(true);
foreach (var entry in archive.Entries)
{
if (entry.IsDirectory) continue;
foreach (var entry in archive.Entries) {
if (!entry.IsDirectory) {
// Is this the entry we are looking for? // Is this the entry we are looking for?
string entryname = entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); string entryname = entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
if (string.Compare(entryname, filename, true) == 0) { if (string.Compare(entryname, filename, true) == 0)
{
filedata = new MemoryStream(); filedata = new MemoryStream();
entry.WriteTo(filedata); entry.WriteTo(filedata);
break; break;
} }
} }
}
UpdateArchive(false);
} }
// Nothing found? // Nothing found?
if (filedata == null){ if (filedata == null)
{
//mxd //mxd
General.ErrorLogger.Add(ErrorType.Error, "Cannot find the file " + filename + " in archive " + location.location + "."); General.ErrorLogger.Add(ErrorType.Error, "Cannot find the file '" + filename + "' in archive '" + location.location + "'.");
return new MemoryStream(); return null;
} }
filedata.Position = 0; //mxd. rewind before use filedata.Position = 0; //mxd. rewind before use
@ -402,12 +443,6 @@ namespace CodeImp.DoomBuilder.Data
return tempfile; return tempfile;
} }
// Public version to load a file
internal MemoryStream ExtractFile(string filename)
{
return LoadFile(filename);
}
#endregion #endregion
} }
} }