Skip to content

Commit 581e01f

Browse files
authoredMar 13, 2025
Fix out of memory error with very large RetentionTimes table (#3389)
Fixed out of memory error reading very large .blib file (reported by Mike)
1 parent 8f3dd8c commit 581e01f

File tree

1 file changed

+55
-22
lines changed

1 file changed

+55
-22
lines changed
 

‎pwiz_tools/Skyline/Model/Lib/BiblioSpecLite.cs

+55-22
Original file line numberDiff line numberDiff line change
@@ -629,13 +629,29 @@ private enum ScoreTypeHeader
629629
// ReSharper restore InconsistentNaming
630630
// ReSharper restore UnusedMember.Local
631631

632-
private MemoryStream CreateCache(ILoadMonitor loader, IProgressStatus status, int percent)
632+
/// <summary>
633+
/// Read entries from the database and create a .slc file.
634+
/// Returns true if successful, otherwise false.
635+
/// <paramref name="memoryStream"/> will be set to
636+
/// </summary>
637+
private bool CreateCache(ILoadMonitor loader, IProgressStatus status, int percent, out MemoryStream memoryStream)
633638
{
634-
MemoryStream outStream;
639+
memoryStream = null;
635640
var sm = loader.StreamManager;
636641
EnsureConnections(sm);
637-
using (SQLiteCommand select = new SQLiteCommand(_sqliteConnection.Connection))
642+
using FileSaver fs = new FileSaver(CachePath, sm);
643+
Stream cacheFileStream = null;
644+
try
645+
{
646+
cacheFileStream = sm.CreateStream(fs.SafeName, FileMode.Create, true);
647+
}
648+
catch (Exception)
638649
{
650+
// The cache will be entirely kept in memory if the file stream could not be created
651+
}
652+
using (cacheFileStream)
653+
{
654+
using SQLiteCommand select = new SQLiteCommand(_sqliteConnection.Connection);
639655
int rows;
640656
string lsid;
641657
int dataRev, schemaVer;
@@ -741,14 +757,14 @@ private MemoryStream CreateCache(ILoadMonitor loader, IProgressStatus status, in
741757
int rowsRead = 0;
742758
while (reader.Read())
743759
{
744-
int percentComplete = rowsRead++*percent/rows;
760+
int percentComplete = rowsRead++ * percent / rows;
745761
if (status.PercentComplete != percentComplete)
746762
{
747763
// Check for cancellation after each integer change in percent loaded.
748764
if (loader.IsCanceled)
749765
{
750766
loader.UpdateProgress(status.Cancel());
751-
return null;
767+
return false;
752768
}
753769

754770
// If not cancelled, update progress.
@@ -877,10 +893,24 @@ private MemoryStream CreateCache(ILoadMonitor loader, IProgressStatus status, in
877893
}
878894

879895
}
880-
881-
outStream = new MemoryStream();
896+
897+
// Start out writing to a memory stream
898+
Stream outStream = memoryStream = new MemoryStream();
899+
// Write the memory stream out to disk when it gets bigger maxMemoryStreamSize
900+
const long maxMemoryStreamSize = 10_000_000;
901+
882902
foreach (var info in libraryEntries)
883903
{
904+
if (cacheFileStream != null && memoryStream?.Length > maxMemoryStreamSize)
905+
{
906+
// Write out the memory stream if it is too big and switch to using the file stream
907+
memoryStream.Seek(0, SeekOrigin.Begin);
908+
memoryStream.CopyTo(cacheFileStream);
909+
outStream = cacheFileStream;
910+
// The memory stream is now incomplete and should not be used by the caller
911+
memoryStream = null;
912+
}
913+
884914
// Write the spectrum header - order must match enum SpectrumCacheHeader
885915
info.Key.Write(outStream);
886916
outStream.Write(BitConverter.GetBytes(info.Copies), 0, sizeof (int));
@@ -962,26 +992,31 @@ private MemoryStream CreateCache(ILoadMonitor loader, IProgressStatus status, in
962992
outStream.Write(BitConverter.GetBytes(libraryEntries.Count), 0, sizeof (int));
963993
outStream.Write(BitConverter.GetBytes(sourcePosition), 0, sizeof (long));
964994
outStream.Write(BitConverter.GetBytes(scoreTypesPosition), 0, sizeof(long));
965-
try
995+
if (cacheFileStream != null)
966996
{
967-
using (FileSaver fs = new FileSaver(CachePath, sm))
968-
using (Stream cacheFileStream = sm.CreateStream(fs.SafeName, FileMode.Create, true))
997+
if (memoryStream != null)
998+
{
999+
memoryStream.Seek(0, SeekOrigin.Begin);
1000+
memoryStream.CopyTo(cacheFileStream);
1001+
}
1002+
sm.Finish(cacheFileStream);
1003+
try
9691004
{
970-
outStream.Seek(0, SeekOrigin.Begin);
971-
outStream.CopyTo(cacheFileStream);
972-
sm.Finish(cacheFileStream);
9731005
fs.Commit();
9741006
sm.SetCache(FilePath, CachePath);
9751007
}
976-
}
977-
catch
978-
{
979-
// ignore
1008+
catch
1009+
{
1010+
// failure to commit the FileSaver can be ignored if we still have the memoryStream
1011+
if (memoryStream == null)
1012+
{
1013+
throw;
1014+
}
1015+
}
9801016
}
9811017
}
982-
9831018
loader.UpdateProgress(status.Complete());
984-
return outStream;
1019+
return true;
9851020
}
9861021

9871022
private Dictionary<int, string> ProteinsBySpectraID()
@@ -1057,12 +1092,10 @@ private bool Load(ILoadMonitor loader, IProgressStatus status, bool cached)
10571092
status = status.ChangePercentComplete(0);
10581093
loader.UpdateProgress(status);
10591094

1060-
cacheBytes = CreateCache(loader, status, 100 - loadPercent);
1061-
if (cacheBytes == null)
1095+
if (!CreateCache(loader, status, 100 - loadPercent, out cacheBytes))
10621096
{
10631097
return false;
10641098
}
1065-
10661099
}
10671100

10681101
status = status.ChangeMessage(string.Format(LibResources.BiblioSpecLiteLibraryLoadLoading__0__library,

0 commit comments

Comments
 (0)