内存使用量相对于Dictionary <t,t> OR List <t>减少/增加

时间:2015-05-01 05:48:39

标签: list c#-4.0 memory-management dictionary

我有一个运行大量数据的项目。我们使用的主要存储是Dictionary。实际上创建了数以千计的词典。将其更改为List for keys和List for values(我们自己实现了IDictionary)后,内存使用量减少了大约30-40%。

为什么?

2 个答案:

答案 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[] bucketsint 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)。