Ich versuche, eine große HashMap<K, V>
zu Vec<(K, V)>
zu konvertieren. Der üblicher Weg, es zu tun wie folgt aussieht:Speichereffiziente Umwandlung zwischen einer HashMap und einem Vec
// initialize HashMap
let cap = 50000000;
let mut hm: HashMap<usize, usize> = HashMap::new();
for i in 0..cap {
hm.insert(i, i);
}
// convert HashMap to Vec
let vec = hm.into_iter().collect::<Vec<(usize, usize)>>();
Dieser Code funktioniert nicht gut, wenn HashMap
groß genug ist - am Anfang des Anrufs collect()
, wird die ursprünglichen HashMap
noch in Erinnerung sein und Vec
wird zugeordnet mit der Kapazität der unteren Größe Hinweis aus der Iterator
entnommen. Dies verursacht eine nicht genügend Speicher-Panik für wirklich große HashMap
s, obwohl ich in der Lage sein sollte zwischen diesen beiden Typen mit sehr wenig zusätzlichen Speicheraufwand zu konvertieren. Bisher habe ich kam mit der folgenden Lösung:
// create small vector
let mut vec: Vec<(usize, usize)> = Vec::with_capacity(100);
for i in hm.into_iter() {
vec.push(i);
// reserve few megabytes
if vec.capacity() - vec.len() < 10 {
vec.reserve_exact(1000000);
}
}
Gibt es einen besseren (effizientere oder idiomatischen) Ansatz für dieses Problem? Ich bin bereit, unsafe
Code zu verwenden, wenn es Leistung verbessern würde.
bearbeiten Wie bereits into_iter
aus während der Iteration nicht freigeben, so dass die vorgeschlagene Lösung nicht wie vorgesehen. Gibt es eine andere Möglichkeit, diese Sammlungen zu konvertieren von HashMap
in die Datei und dann lesen Sie diese Datei in Vec
?
Sind Sie sicher, dass Ihr zweiter Code weniger Arbeitsspeicher hat? Ich glaube nicht, dass der Iterator "IntoIter" während der Iteration Speicher freigibt. Eigentlich ist es nicht einfach, diese Konversation mit wenig zusätzlichem Speicher durchzuführen ... –
Wenn nicht genug Speicher vorhanden ist, um sowohl die 'HashMap' als auch die' Vec' gleichzeitig zu speichern, können Sie den Computer wechseln, oder restrukturieren Sie Ihr Programm, um kleinere Arbeitsbereiche bearbeiten zu können (z. B. MapReduce). So wie es ist, haben Sie sehr wenig Spielraum: Wenn die Problemgröße um 50% steigt, könnten Sie sehr wohl mit * nur * der HashMap arbeiten, und was werden Sie tun? –