J'ai de gros fichiers binaires que je lis dans des structures, puis j'ajoute ces structures à une liste pour pouvoir les parcourir plus tard. Tout fonctionne bien, sauf que la lecture dans les structures se fait plus lentement que prévu. Voici le code correspondant:Comment augmenter les performances de lecture de gros fichier binaire dans les structures?
//128 bytes total
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct RAMPrec2
{
public double now; // Days in double precision (see note 1)
public int VehLatitude; // Milliarcseconds (see note 2)
public int VehLongitude; // Milliarcseconds (see note 2)
public short VehLatUncertainty; // Meters as 16-bit int
public short VehLonUncertainty; // Meters as 16-bit int
public short Reserved1; // Meters as 16-bit int (see note 3)
public short Reserved2; // Meters as 16-bit int
public float VehAltitude; // Meters as a float
public float VehFirstRet; // Meters as a float
public float VehDepth; // Meters as a float
public float VehSpeed; // Knots as a float
public float VehHeading; // degrees as a float (e.g. 0.0 - 359.9999)
public float VehCourse; // degrees as a float (e.g. 0.0 - 359.9999)
public float VehRoll; // degrees as a float (positive is counterclockwise roll)
public float VehPitch; // degrees as a float (negative is downward pitch)
public float VehVOS; // Meters/sec
public int DisplayNorthing; // Centimeters as 32-bit integer
public int DisplayingEasting; // Centimeters as 32-bit integer
public int OriginalLatitude; // Milliarcseconds as 32-bit integer
public int OriginalLongitude; // Milliarcseconds as 32-bit integer
public int DeltaNorthing; // Centimeters as 32-bit integer
public int DeltaEasting; // Centimeters as 32-bit integer
public short FixFlags; // 16 bit flags. (note 5)
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] // 8 sets of 32-bit values,sensor specific (note 3)
public int[] SData;
public ushort DataAvailFlags; // 16 bit mask field (note 4)
public ushort QA_Flag; // 16 bit mask field (note 6)
public short EventFlag; // 2-byte reserved field
public float Reserved3; // 4-byte reserved field
}
public Boolean ReadRampFileType2(List<string> rampPaths) //rampPaths is just a list of filepaths for each binary file to be read
{
for (int i = 0; i < rampPaths.Count; i++)
{
try
{
using (var stream = new FileStream(rampPaths[i], FileMode.Open, FileAccess.Read, FileShare.None)) //open up a stream on the specified file
{
stream.Position = 8192; //skip header
while (stream.Position < (stream.Length)) //while not at end of file
{
RAMPrec2 ramp = ReadRecFromStream<RAMPrec2>(stream, Marshal.SizeOf(typeof(RAMPrec2))); //read in each record to the ramp struct
AddRecDataToListsType2(ramp, vehicles[i]);
}
}
}
catch (Exception e) //something went wrong
{
return false;
}
}
return true;
}
private T ReadRecFromStream<T>(Stream stream, int size) where T : struct
{
byte[] buffer = new byte[Marshal.SizeOf(typeof(T))];
stream.Read(buffer, 0, size);
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
}
//I have a vehicle class with a bunch of lists. This adds the data from the structs I read in to these lists
public void AddRecDataToListsType2(RAMPrec2 ramp, VehicleModel vehicle)
{
vehicle.NowTime.Add(ramp.now);
vehicle.VehLat.Add(ramp.VehLatitude/MILLIARCTODEG);
vehicle.VehLong.Add(ramp.VehLongitude/MILLIARCTODEG);
vehicle.VehHead.Add(ramp.VehHeading);
vehicle.VehSpeed.Add(ramp.VehSpeed);
vehicle.VehTWD.Add(ramp.VehAltitude + ramp.VehDepth);
vehicle.VehAlt.Add(ramp.VehAltitude);
vehicle.VehDep.Add(ramp.VehDepth);
vehicle.VehRoll.Add(ramp.VehRoll);
vehicle.VehPit.Add(ramp.VehPitch);
}
boucle I dans la liste des fichiers binaires que j'ai et ouvrir un flux de fichiers sur chacun, passez à la position où la première « struct » apparaît dans le fichier binaire, puis lire que dans une structure, qui a ensuite ses champs ajoutés à un tas de listes, puis je répète jusqu'à la fin du fichier. C'est lent, et je pense qu'il doit y avoir une meilleure façon de faire les choses.
Combien et quelle taille sont vos fichiers? Eh bien, il semble que vous tombez sur les limites de vitesse de lecture de stockage. Il n'y a rien que vous pouvez faire en dehors de la mise à niveau vers SSD. –
Seulement comme 400mb, peut-être plus grand, avec 1 'struct' pour chaque 128 octets. Mais il y a des multiples de ces fichiers. 4 tout au plus en ce moment. – pfinferno
utilise 'while (! Stream.EndOfStream)'. Et chaque fois que vous appelez '.Length', le système doit vérifier la longueur du flux ou du tableau. Il y a beaucoup de raisons pour lesquelles c'est lent. Je verrai si je peux vous construire une méthode plus rapide (la première chose est de se débarrasser de toutes les allocations et appels de méthode si vous voulez la meilleure performance.) –