выводить словарь оптимально - PullRequest
1 голос
/ 28 марта 2012

У меня есть 4 словаря, которые содержат 800 тыс. Строк с 200 до 6000 символов.когда я загружаю его в память, это занимает около 11 гигабайт памяти.у меня уходит 2 минуты на анализ данных и 2 минуты на вывод данных.Есть ли способ вывести данные быстрее, чем я использую ниже?Я получаю только 20-31 МБ в секунду дискового ввода-вывода и знаю, что жесткий диск может делать 800ish

var hash1 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash2 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash3 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
var hash4 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2);
....
foreach (var me in mswithfilenames)
{
    filename = me.Key.ToString();
    string filenamef = filename + "index1";
    string filenameq = filename + "index2";
    string filenamefq = filename + "index3";
    string filenameqq = filename + "index4";

    StreamWriter sw = File.AppendText(filenamef);
    StreamWriter sw2 = File.AppendText(filenameq);
    StreamWriter swq = File.AppendText(filenamefq);
    StreamWriter sw2q = File.AppendText(filenameqq);

    for (i = 0; i <= totalinhash; i++)
    {
        if (hashs1[i].ContainsKey(filenamef))
        {
            sw.Write(hashs1[i][filenamef]);
        }
        if (hashs2[i].ContainsKey(filenameq))
        {
            sw2.Write(hashs2[i][filenameq]);
        }
        if (hashs3[i].ContainsKey(filenamefastaq))
        {
            swq.Write(hash4[i][filenamefastaq]);
        }

        if (hash4[i].ContainsKey(filenameqq))
        {
            sw2q.Write(hash4[i][filenameqq]);
        }
    }

    sw.Close();
    sw2.Close();
    sw3.Close();
    sw4.Close();
    swq.Close();
    sw2q.Close();
}

Ответы [ 4 ]

3 голосов
/ 28 марта 2012

Вы что-нибудь измеряли?Похоже, у вас есть нетривиальный объем данных для чтения и записи - поэтому первым шагом будет установление абсолютной базовой линии для вашей дисковой подсистемы о том, насколько быстро она читает / записывает такое количество данных.Простое чтение файла с последующей записью в новый файл приблизительного объема данных, который вы ожидаете, покажет, насколько далеко вы можете продвинуться в его оптимизации.

Вы можете заметить, что сам код не занимает слишком много временичтение / запись.

2 голосов
/ 28 марта 2012

Самая дорогая часть - это ввод / вывод. И этот цикл:

for (i = 0; i <= totalinhash; i++)
{
    if (hashs1[i].ContainsKey(filenamef))
    {
        sw.Write(hashs1[i][filenamef]);
    }
    if (hashs2[i].ContainsKey(filenameq))
    {
        sw2.Write(hashs2[i][filenameq]);
    }
    ...
}

чередуется между разными файлами. Это, вероятно, вызовет дополнительное движение головы и создаст фрагментированные файлы (замедляя будущие действия с этими файлами).

Я бы использовал:

for (i = 0; i <= totalinhash; i++)
{
    if (hashs1[i].ContainsKey(filenamef))
    {
        sw.Write(hashs1[i][filenamef]);
    }
}

for (i = 0; i <= totalinhash; i++)
{
    if (hashs2[i].ContainsKey(filenameq))
    {
        sw2.Write(hashs2[i][filenameq]);
    }
}
...

Но, конечно, вы должны это измерить. Например, это не будет иметь большого значения для SSD, только для механических дисков.

1 голос
/ 28 марта 2012

Можете ли вы иметь Dictionary<int, Dictionary<string, myCustomDataHolder>> вместо четырех отдельных параллелей Dictionary<int, Dictionary<string, string>? Это не только должно уменьшить занимаемое пространство, но также означает, что поиск по словарю составляет 1/4.

Не совсем ясно, являются ли словари полностью параллельными с учетом вашего вопроса, но мне это кажется достаточно вероятным.

0 голосов
/ 18 мая 2012

Я бы хотел добавить это

if (hashs1[i].ContainsKey(filenamef))
{
   sw.Write(hashs1[i][filenamef]);
}

Получает 2 доступа к хеш-таблице. Один для ключа содержит, а другой для фактического доступа. Многие обращения к словарям могут складываться, поэтому вы можете вдвое сократить доступ к ним, используя метод словаря tryGetValue. Это объединит эти два вызова в один. Я мог бы объяснить, как это работает, но это делает работу лучше, чем я мог: http://www.dotnetperls.com/trygetvalue

...