У меня есть несколько очень больших файлов XML, которые я читаю, используя System.Xml.Serialization.XmlSerializer
. Это довольно быстро (ну, достаточно быстро), но я хочу, чтобы он объединял строки, так как некоторые длинные строки встречаются очень часто.
XML выглядит примерно так:
<Report>
<Row>
<Column name="A long column name!">hey</Column>
<Column name="Another long column name!!">7</Column>
<Column name="A third freaking long column name!!!">hax</Column>
<Column name="Holy cow, can column names really be this long!?">true</Column>
</Row>
<Row>
<Column name="A long column name!">yo</Column>
<Column name="Another long column name!!">53</Column>
<Column name="A third freaking long column name!!!">omg</Column>
<Column name="Holy cow, can column names really be this long!?">true</Column>
</Row>
<!-- ... ~200k more rows go here... -->
</Report>
И классы, на которые XML десериализован, выглядят примерно так:
class Report
{
public Row[] Rows { get; set; }
}
class Row
{
public Column[] Columns { get; set; }
}
class Column
{
public string Name { get; set; }
public string Value { get; set; }
}
Когда данные импортируются, для каждого имени столбца выделяется новая строка. Я понимаю, почему это так, но, согласно моим расчетам, это означает, что несколько дублированных строк занимают около 50% памяти, используемой импортированными данными. Я считаю очень хорошим компромиссом потратить несколько дополнительных циклов ЦП, чтобы сократить потребление памяти в два раза. Есть ли какой-нибудь способ получить строки пула XmlSerializer
, чтобы дубликаты отбрасывались и могли быть возвращены при следующем GC gen0?
<Ч />
Также несколько заключительных замечаний:
Я не могу изменить схему XML. Это экспортированный файл от стороннего поставщика.
Я знаю, что (теоретически) мог бы создать более быстрый синтаксический анализатор, используя вместо этого XmlReader
, и это позволило бы мне не только выполнять собственный пул строк, но и обрабатывать данные во время промежуточного импорта, чтобы не все 200k строк должны быть сохранены в оперативной памяти, пока я не прочитал весь файл. Тем не менее, я бы не стал тратить время на написание и отладку пользовательского парсера. Настоящий XML немного сложнее, чем пример, поэтому это довольно нетривиальная задача. И, как упоминалось выше, XmlSerializer
действительно достаточно хорошо работает для моих целей, мне просто интересно, есть ли простой способ немного его настроить.
Я мог бы написать собственный пул строк и использовать его в установщике Column.Name
, но я бы предпочел не как (1), что означает возиться с автоматически сгенерированным кодом, и (2) он открывается на множество проблем, связанных с параллелизмом и утечками памяти.
И нет, под «объединением» я не подразумеваю «интернирование», поскольку это может вызвать утечки памяти.