2009-07-20 3 views
0

Я разрабатываю приложение, которое использует очень большие таблицы поиска для ускорения математических вычислений. Самая большая из этих таблиц - это int [], которая имеет ~ 10 миллионов записей. Не все таблицы поиска являются int []. Например, один словарь с ~ 200 000 записей. В настоящее время я генерировать каждую таблицу поиска один раз (который занимает несколько минут) и сериализовать его на диск (со сжатием), используя следующий фрагмент кода:Хранение таблиц большого поиска

int[] lut = GenerateLUT(); 
    lut.Serialize("lut"); 

, где Сериализация определяются следующим образом:

public static void Serialize(this object obj, string file) 
    { 
     using (FileStream stream = File.Open(file, FileMode.Create)) 
     { 
      using (var gz = new GZipStream(stream, CompressionMode.Compress)) 
      { 
       var formatter = new BinaryFormatter(); 
       formatter.Serialize(gz, obj); 
      } 
     } 
    } 

досада, которую я испытываю при запуске приложения, заключается в том, что десериализация этих поисковых таблиц занимает очень много времени (более 15 секунд). Этот тип задержки будет раздражать пользователей, так как приложение будет непригодным до тех пор, пока не будут загружены все таблицы поиска. В настоящее время десериализации выглядит следующим образом:

 int[] lut1 = (Dictionary<string, int>) Deserialize("lut1"); 
    int[] lut2 = (int[]) Deserialize("lut2"); 
... 

где Deserialize определяется как:

public static object Deserialize(string file) 
    { 
     using (FileStream stream = File.Open(file, FileMode.Open)) 
     { 
      using (var gz = new GZipStream(stream, CompressionMode.Decompress)) 
      { 
       var formatter = new BinaryFormatter(); 
       return formatter.Deserialize(gz); 
      } 
     } 
    } 

Сначала я думал, что это, возможно, было сжатие GZIP, который вызывает замедление, но удаление это только обезжиренное в нескольких сотнях миллисекунд из процедур Serialization/Deserialization.

Может ли кто-нибудь предложить способ ускорения времени загрузки этих таблиц поиска при первом запуске приложения?

ответ

2

Во-первых, десериализация в фоновом потоке предотвратит «зависание» приложения, пока это произойдет. Этого может быть достаточно, чтобы позаботиться о вашей проблеме.

Однако сериализация и десериализация (особенно больших словарей) в целом являются очень медленными. В зависимости от структуры данных, запись собственного кода сериализации может значительно ускорить это, особенно если в структурах данных нет общих ссылок.

Учитывая, что в зависимости от шаблона использования, база данных может быть лучшим подходом. Вы всегда можете сделать что-то более ориентированное на базу данных и строить таблицу поиска в ленивом виде из БД (т. Е. Поиск выполняется в LUT, но если поиск не существует, загрузите его из БД и сохраните это в таблице). Это сделало бы запуск мгновенным (по крайней мере, с точки зрения LUT) и, вероятно, по-прежнему сохранял бы поиск довольно быстро.

0

Я думаю, очевидное предложение - загрузить их в фоновом режиме. После того, как приложение запустилось, пользователь открыл свой проект и выбрал любую операцию, в которой они хотят, осталось недолго, чтобы осталось 15 секунд.

+0

Я согласен с этим, но это все-таки обходное решение imo. Что касается моего приложения, gui достаточно просто, чтобы пользователь был готов выполнить вычисление менее чем за 5 секунд. Поэтому на данный момент я стремлюсь к времени загрузки 5 секунд или меньше (где таблицы поиска будут загружены в фоновом режиме менее чем за 5 секунд). – snazzer

0

Как много данных мы говорим здесь? По моему опыту, для чтения гигабайта с диска в память требуется около 20 секунд. Поэтому, если вы читаете до половины гигабайта, вы почти наверняка используете аппаратные ограничения.

Если скорость передачи данных не является проблемой, то фактическая десериализация занимает много времени. Если у вас достаточно памяти, вы можете загрузить все таблицы в буферы памяти (используя File.ReadAllBytes()), а затем десериализовать из потока памяти. Это позволит вам определить, сколько времени занимает чтение, и сколько времени занимает десериализация.

Если десериализация занимает много времени, вы можете, если у вас есть несколько процессоров, вызвать несколько threds для параллелизации сериализации.С такой системой вы потенциально можете десериализовать одну или несколько таблиц при загрузке данных для другого. Этот конвейерный подход может сделать ваше время загрузки/десериализации практически таким же быстрым, как и загрузка.

+0

Общее количество данных на диске таблиц поиска меньше 100 мегабайт, поэтому я считаю, что ограничения на передачу данных можно исключить. – snazzer

0

Другой вариант - разместить ваши таблицы, ну, таблицы: таблицы реальной базы данных. Даже такой движок, как Access, должен давать довольно хорошую производительность, потому что у вас есть очевидный индекс для каждого запроса. Теперь приложение должно читать только данные, когда на самом деле собирается его использовать, и даже тогда он точно узнает, где искать файл.

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

0

Зачем молчать?

Диск больше, чем ОЗУ.

Прямое двоичное чтение должно быть довольно быстрым.

Смежные вопросы