J'ai utilisé BinaryFormatter pour sérialiser des données sur le disque mais cela ne semble pas très évolutif. J'ai créé un fichier de données de 200 Mo mais je suis incapable de le relire (Fin du flux rencontré avant l'achèvement de l'analyse). Il essaie pendant environ 30 minutes de se désérialiser puis abandonne. C'est sur une boîte quad-cpu assez décente avec 8 Go de RAM.C# données sérialisées
Je suis en train de sérialiser une structure assez complexe.
htCacheItems est une Hashtable de CacheItems. Chaque CacheItem a plusieurs membres simples (chaînes + ints etc) et contient également une Hashtable et une implémentation personnalisée d'une liste chaînée. La sous-table de hachage pointe vers les structures CacheItemValue qui est actuellement un simple DTO qui contient une clé et une valeur. Les éléments de la liste liée sont également simples.
Le fichier de données qui échoue contient environ 400 000 CacheItemValues.
De plus petits ensembles de données fonctionnent bien (bien que cela prenne plus de temps que je m'attendrais à désérialiser et utiliser beaucoup de mémoire).
public virtual bool Save(String sBinaryFile)
{
bool bSuccess = false;
FileStream fs = new FileStream(sBinaryFile, FileMode.Create);
try
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, htCacheItems);
bSuccess = true;
}
catch (Exception e)
{
bSuccess = false;
}
finally
{
fs.Close();
}
return bSuccess;
}
public virtual bool Load(String sBinaryFile)
{
bool bSuccess = false;
FileStream fs = null;
GZipStream gzfs = null;
try
{
fs = new FileStream(sBinaryFile, FileMode.OpenOrCreate);
if (sBinaryFile.EndsWith("gz"))
{
gzfs = new GZipStream(fs, CompressionMode.Decompress);
}
//add the event handler
ResolveEventHandler resolveEventHandler = new ResolveEventHandler(AssemblyResolveEventHandler);
AppDomain.CurrentDomain.AssemblyResolve += resolveEventHandler;
BinaryFormatter formatter = new BinaryFormatter();
htCacheItems = (Hashtable)formatter.Deserialize(gzfs != null ? (Stream)gzfs : (Stream)fs);
//remove the event handler
AppDomain.CurrentDomain.AssemblyResolve -= resolveEventHandler;
bSuccess = true;
}
catch (Exception e)
{
Logger.Write(new ExceptionLogEntry("Failed to populate cache from file " + sBinaryFile + ". Message is " + e.Message));
bSuccess = false;
}
finally
{
if (fs != null)
{
fs.Close();
}
if (gzfs != null)
{
gzfs.Close();
}
}
return bSuccess;
}
Le resolveEventHandler est juste un travail autour parce que je suis sérialisation les données dans une seule application et le charger dans un autre (http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/e5f0c371-b900-41d8-9a5b-1052739f2521)
La question est, comment puis-je améliorer cela? La sérialisation des données va toujours être inefficace, est-ce que je préfère écrire mes propres routines?
Ajout d'un exemple qui essaie d'imiter votre description. –
(corrigé le problème avec la liste chaînée; r263.) Note: Je n'ai pas relibéré le binaire, si vous voulez le faire, ajoutez un commentaire à mon message, ou envoyez-moi un e-mail (voir profil) –