我有一个运行大量数据的项目。我们使用的主要存储是Dictionary。实际上创建了数以千计的词典。将其更改为List for keys和List for values(我们自己实现了IDictionary)后,内存使用量减少了大约30-40%。
为什么?
答案 0 :(得分:2)
如果你对它们进行排序并将它们放在一个数组中,你可以节省另外30%的内存。
特色成本记忆,你知道吗?
Dictionary<,>
为您提供了一个 O(1) Add()
和TryGetValue()
List<>
以较低的价格为您提供 O(1) Add()
,如果已排序,则为 O(logn) BinarySearch()
,但请注意,为了保持排序,您无法使用Add()
,您必须使用Insert()
,即 O(n)
T[]
以更低的价格为您提供 O(logn) BinarySearch()
。从技术上讲,你可以有一个 O(n)插入,但是你必须手动完成(并且“实际”成本会比List<>
更大)< / p>
现在......如果您想知道Dictionary<,>
如何使用您宝贵的记忆,您可以查看reference source
有struct
:
private struct Entry {
public int hashCode; // Lower 31 bits of hash code, -1 if unused
public int next; // Index of next entry, -1 if last
public TKey key; // Key of entry
public TValue value; // Value of entry
}
有两个数组,其中一个使用这个结构:
private int[] buckets;
private Entry[] entries;
因此List<TKey>
+ List<TValue>
可能小于Dictionary<TKey, TValue>
,因为Dictionary<,>
还有int[] buckets
加int hashCode
每个元素都有一个int next
。
请注意,Dictionary<,>
和List<>
的增长算法不同。 List<>
通过将元素数量加倍来增长,而Dictionary<,>
通过将元素数量加倍然后找到大于此数的素数来增长。所以Dictionary<,>
增长得快一点。
答案 1 :(得分:1)
几年前,我对package com.rhoads.teamwork.backup;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;
public class TeamworkBackup {
public static void main(String[] args) throws Exception {
WebDriver driver;
String baseUrl;
driver = new ChromeDriver();
baseUrl = "https://myco.teamwork.com/index.cfm";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get(baseUrl + "/");
Thread.sleep(4000);
driver.findElement(By.id("password")).clear();
driver.findElement(By.id("password")).sendKeys("superstrong");
driver.findElement(By.id("userLogin")).clear();
driver.findElement(By.id("userLogin")).sendKeys("someguy@example.com");
driver.findElement(By.id("ordLoginSubmitBtn")).click();
Thread.sleep(4000);
driver.get("https://myco.teamwork.com/settings?display=export");
Thread.sleep(4000);
driver.switchTo().frame("backupFrame");
Thread.sleep(4000);
driver.findElement(By.linkText("Download")).click();
Thread.sleep(4000);
driver.quit();
}
}
内存使用情况进行了分析。简而言之,Dictionary
的开销是每个项目24个字节。那是64位运行时。有关详细信息,请参阅More on .NET Collection Sizes。
Dictionary<TKey, TValue>
开销是每个项目8个字节:保存对列表中项目的引用所需的数据量。您交换了一个字典,每个项目的开销为24字节,两个列表,每个项目开销为8个字节。所以你的总开销是每个项目16个字节。
16是24的2/3。所以你节省了大约33%。
您遇到的可能是传统的尺寸/速度权衡。字典为您提供O(1)查找但使用更多内存。使用两个列表,可以节省内存,但查找为O(log n)。