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
if(loadfinishtime == 0)
{
//mxd. Release PK3 files
foreach (DataReader reader in containers)
{
if (reader is PK3Reader) (reader as PK3Reader).BathMode = false;
}
loadfinishtime = Clock.CurrentTime;
float deltatimesec = (loadfinishtime - loadstarttime) / 1000.0f;
General.WriteLogLine("Resources loading took " + deltatimesec.ToString("########0.00") + " seconds");
@ -1408,7 +1414,7 @@ namespace CodeImp.DoomBuilder.Data
}
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;
}

View file

@ -74,7 +74,7 @@ namespace CodeImp.DoomBuilder.Data
{
// Load file data
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
IImageReader reader = ImageDataFormat.GetImageReader(filedata, probableformat, General.Map.Data.Palette);

View file

@ -32,9 +32,17 @@ namespace CodeImp.DoomBuilder.Data
{
#region ================== Variables
private DirectoryFilesList files;
private ArchiveType archiveType; //mxd
private static Dictionary<string, byte[]> sevenZipEntries; //mxd
private readonly DirectoryFilesList files;
private IArchive archive; //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
@ -51,35 +59,38 @@ namespace CodeImp.DoomBuilder.Data
// Make list of all files
List<DirectoryFileEntry> fileentries = new List<DirectoryFileEntry>();
//mxd
IArchive archive = ArchiveFactory.Open(location.location);
archiveType = archive.Type;
// Create archive
archive = ArchiveFactory.Open(location.location, Options.KeepStreamsOpen);
archivetype = archive.Type;
if (archive.Type == ArchiveType.SevenZip) { //random access of 7z archives works TERRIBLY slow in SharpCompress
sevenZipEntries = new Dictionary<string, byte[]>(StringComparer.Ordinal);
// Random access of 7z archives works TERRIBLY slow in SharpCompress
if(archivetype == ArchiveType.SevenZip)
{
sevenzipentries = new Dictionary<string, byte[]>(StringComparer.Ordinal);
IReader reader = archive.ExtractAllEntries();
while (reader.MoveToNextEntry()) {
if (!reader.Entry.IsDirectory) {
MemoryStream s = new MemoryStream();
reader.WriteEntryTo(s);
sevenZipEntries.Add(reader.Entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), s.ToArray());
fileentries.Add(new DirectoryFileEntry(reader.Entry.FilePath));
}
}
//archive.Dispose();
//archive = null;
while(reader.MoveToNextEntry())
{
if(reader.Entry.IsDirectory) continue;
} else {
foreach (IEntry entry in archive.Entries) {
if (!entry.IsDirectory)
fileentries.Add(new DirectoryFileEntry(entry.FilePath));
MemoryStream s = new MemoryStream();
reader.WriteEntryTo(s);
sevenzipentries.Add(reader.Entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), s.ToArray());
fileentries.Add(new DirectoryFileEntry(reader.Entry.FilePath));
}
archive.Dispose();
archive = null;
}
else
{
foreach(IArchiveEntry entry in archive.Entries)
{
if(entry.IsDirectory) continue;
fileentries.Add(new DirectoryFileEntry(entry.FilePath));
}
}
archive.Dispose();
archive = null;
// Make files list
files = new DirectoryFilesList(fileentries);
@ -97,13 +108,35 @@ namespace CodeImp.DoomBuilder.Data
if(!isdisposed)
{
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
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
#region ================== Textures
@ -349,7 +382,7 @@ namespace CodeImp.DoomBuilder.Data
{
string title = Path.GetFileNameWithoutExtension(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);
}
@ -358,32 +391,40 @@ namespace CodeImp.DoomBuilder.Data
internal override MemoryStream LoadFile(string filename)
{
MemoryStream filedata = null;
//mxd
if (archiveType == ArchiveType.SevenZip) { //this works waaaaaay faster with 7z archive
if (sevenZipEntries.ContainsKey(filename))
filedata = new MemoryStream(sevenZipEntries[filename]);
} else {
IArchive archive = ArchiveFactory.Open(location.location);
foreach (var entry in archive.Entries) {
if (!entry.IsDirectory) {
// Is this the entry we are looking for?
string entryname = entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
if (string.Compare(entryname, filename, true) == 0) {
filedata = new MemoryStream();
entry.WriteTo(filedata);
break;
}
//mxd. This works waaaaaay faster with 7z archive
if (archivetype == ArchiveType.SevenZip)
{
if (sevenzipentries.ContainsKey(filename))
filedata = new MemoryStream(sevenzipentries[filename]);
}
else
{
UpdateArchive(true);
foreach (var entry in archive.Entries)
{
if (entry.IsDirectory) continue;
// Is this the entry we are looking for?
string entryname = entry.FilePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
if (string.Compare(entryname, filename, true) == 0)
{
filedata = new MemoryStream();
entry.WriteTo(filedata);
break;
}
}
UpdateArchive(false);
}
// Nothing found?
if (filedata == null){
if (filedata == null)
{
//mxd
General.ErrorLogger.Add(ErrorType.Error, "Cannot find the file " + filename + " in archive " + location.location + ".");
return new MemoryStream();
General.ErrorLogger.Add(ErrorType.Error, "Cannot find the file '" + filename + "' in archive '" + location.location + "'.");
return null;
}
filedata.Position = 0; //mxd. rewind before use
@ -401,12 +442,6 @@ namespace CodeImp.DoomBuilder.Data
filedata.Dispose();
return tempfile;
}
// Public version to load a file
internal MemoryStream ExtractFile(string filename)
{
return LoadFile(filename);
}
#endregion
}