Я часто сталкиваюсь с проблемами производительности, когда я XSL преобразовываю большие объемы данных в HTML.Эти данные обычно представляют собой пару очень больших таблиц примерно такой формы:
<table>
<record>
<group>1</group>
<data>abc</abc>
</record>
<record>
<group>1</group>
<data>def</abc>
</record>
<record>
<group>2</group>
<data>ghi</abc>
</record>
</table>
Во время преобразования я хочу визуально сгруппировать записи, подобные этой
+--------------+
| Group 1 |
+--------------+
| abc |
| def |
+--------------+
| Group 2 |
+--------------+
| ghi |
+--------------+
Глупая реализацияэтот (набор из http://exslt.org. фактическая реализация немного отличается, это всего лишь пример):
<xsl:for-each select="set:distinct(/table/record/group)">
<xsl:variable name="group" select="."/>
<!-- This access needs to be made faster : -->
<xsl:for-each select="/table/record[group = $group]">
<!-- Do the table stuff -->
</xsl:for-each>
</xsl:for-each>
Легко видеть, что это имеет сложность O(n^2)
.Еще хуже, поскольку в каждой записи много полей.Используемые данные могут достигать нескольких десятков МБ, а количество записей - до 5000. В худшем случае каждая запись имеет свою группу и 50 полей.И, что еще хуже, существует еще один уровень группировки, позволяющий сделать это O(n^3)
Теперь было бы довольно много вариантов:
- Я мог бы найтиРешение Java для этого включает карты и вложенные структуры данных.Но я хочу улучшить свои навыки XSLT, так что это на самом деле последний вариант.
- Возможно, я не обращаю внимания на хорошую функцию в Xerces / Xalan / Exslt, которая может намного лучше справляться с группировкой
- Возможно, я смогу построить какой-нибудь индекс для
/table/record/group
- . Вы можете доказать мне, что подход
<xsl:apply-templates/>
в этом случае определенно быстрее, чем подход <xsl:for-each/>
.
Как вы думаете, как можно уменьшить эту O(n^2)
сложность?