Under a large number of queries and fetches OpenMCDF allocated a large amount of very small objects. The sheer number of objects caused garbage collection to run a large portion of the time.
The first issue spot was in StreamRW, ReadByte and WriteByte both allocate internal one byte arrays then release them at the end of the call. WriteByte was not called enough to be an issue but ReadByte was very active.
See: http://referencesource.microsoft.com/#mscorlib/system/io/stream.cs
Proposed:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public byte ReadByte()
{
this.stream.Read(buffer, 0, 1);
return buffer[0];
//return (byte)this.stream.ReadByte();
}
public void Write(byte b)
{
buffer[0] = b;
this.stream.Write(buffer, 0, 1);
//this.stream.WriteByte(b);
}
Additionally DirectoryEntry.CompareTo was allocating large amounts of memory through the ByteConverter. Characters can be value compared so reducing that to a comparison reduced the amount of memory allocated.
Proposed:
String thisName = Encoding.Unicode.GetString(this.EntryName, 0, this.NameLength);
String otherName = Encoding.Unicode.GetString(otherDir.EntryName, 0, otherDir.NameLength);
for (int z = 0; z < thisName.Length; z++)
{
char thisChar = char.ToUpperInvariant(thisName[z]);
char otherChar = char.ToUpperInvariant(otherName[z]);
if(thisChar > otherChar)
return THIS_IS_GREATER;
else if (thisChar < otherChar)
return OTHER_IS_GREATER;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thank you very much for your extensive report.
Changes will be integrated in 2.0 (dev) branch as soon as possible.
Best Regards,
Federico