linker: Use sequences for stacks (instead of trees)
This has a significant performance impact: processing time is cut in about half and memory usage is reduced by more than 50%. For example, a package that previously took 30s and 2.1GiB of memory to link now takes 14s and less than 900MiB of memory. I had tried to perform this optimization a couple years ago but was thwarted (I think) by the classifier markers. The previous commit did away with those. I'm encouraged by the gains from the low-hanging fruit. * src/current/compiler/linker.xsl (l:process-empty, l:stack-empty): Convert from l:pstack and l:sym-stack (respectively) to empty preproc:sym sequences. (l:depgen-process-sym)[preproc:sym]: Append to sequence rather than outputting new l:sym-stack tree. Update all annotations and uses accordingly.master
parent
f2db9f1268
commit
d624ee6d7e
|
@ -57,13 +57,11 @@
|
||||||
<variable name="l:orig-root" as="document-node( element( lv:package ) )"
|
<variable name="l:orig-root" as="document-node( element( lv:package ) )"
|
||||||
select="/" />
|
select="/" />
|
||||||
|
|
||||||
<variable name="l:process-empty" as="element( l:pstack )">
|
<variable name="l:process-empty" as="element( preproc:sym )*"
|
||||||
<l:pstack />
|
select="()" />
|
||||||
</variable>
|
|
||||||
|
|
||||||
<variable name="l:stack-empty" as="element( l:sym-stack )">
|
<variable name="l:stack-empty" as="element( preproc:sym )*"
|
||||||
<l:sym-stack />
|
select="()" />
|
||||||
</variable>
|
|
||||||
|
|
||||||
|
|
||||||
<template match="*" mode="l:link" priority="1">
|
<template match="*" mode="l:link" priority="1">
|
||||||
|
@ -115,7 +113,7 @@
|
||||||
<l:dep>
|
<l:dep>
|
||||||
<!-- empty stack -->
|
<!-- empty stack -->
|
||||||
<apply-templates select="preproc:symtable" mode="l:depgen">
|
<apply-templates select="preproc:symtable" mode="l:depgen">
|
||||||
<with-param name="stack" select="$l:stack-empty" as="element( l:sym-stack )" />
|
<with-param name="stack" select="$l:stack-empty" />
|
||||||
</apply-templates>
|
</apply-templates>
|
||||||
</l:dep>
|
</l:dep>
|
||||||
</variable>
|
</variable>
|
||||||
|
@ -175,8 +173,8 @@
|
||||||
|
|
||||||
<template mode="l:depgen" as="element( preproc:sym )*"
|
<template mode="l:depgen" as="element( preproc:sym )*"
|
||||||
match="preproc:symtable">
|
match="preproc:symtable">
|
||||||
<param name="stack" as="element( l:sym-stack )"
|
<param name="stack" as="element( preproc:sym )*"
|
||||||
select="$l:stack-empty" />
|
select="()" />
|
||||||
|
|
||||||
<!-- we care only of the symbols used by lv:yields, from which all
|
<!-- we care only of the symbols used by lv:yields, from which all
|
||||||
dependencies may be derived (if it's not derivable from the yield
|
dependencies may be derived (if it's not derivable from the yield
|
||||||
|
@ -209,7 +207,7 @@
|
||||||
<variable name="result" as="element()+">
|
<variable name="result" as="element()+">
|
||||||
<call-template name="l:depgen-sym">
|
<call-template name="l:depgen-sym">
|
||||||
<with-param name="pending" select="$yields" />
|
<with-param name="pending" select="$yields" />
|
||||||
<with-param name="stack" select="$stack" as="element( l:sym-stack )" />
|
<with-param name="stack" select="$stack" />
|
||||||
</call-template>
|
</call-template>
|
||||||
</variable>
|
</variable>
|
||||||
|
|
||||||
|
@ -235,24 +233,24 @@
|
||||||
|
|
||||||
<template name="l:depgen-sym" as="element( preproc:sym )*">
|
<template name="l:depgen-sym" as="element( preproc:sym )*">
|
||||||
<param name="pending" as="element( preproc:sym )*" />
|
<param name="pending" as="element( preproc:sym )*" />
|
||||||
<param name="stack" as="element( l:sym-stack )" />
|
<param name="stack" as="element( preproc:sym )*" />
|
||||||
<param name="path" as="xs:string"
|
<param name="path" as="xs:string"
|
||||||
select="''" />
|
select="''" />
|
||||||
<param name="processing" as="element( l:pstack )"
|
<param name="processing" as="element( preproc:sym )*"
|
||||||
select="$l:process-empty" />
|
select="$l:process-empty" />
|
||||||
|
|
||||||
<variable name="pend-count" as="xs:integer"
|
<variable name="pend-count" as="xs:integer"
|
||||||
select="count( $pending )" />
|
select="count( $pending )" />
|
||||||
<variable name="stack-count" as="xs:integer"
|
<variable name="stack-count" as="xs:integer"
|
||||||
select="count( $stack/preproc:sym )" />
|
select="count( $stack )" />
|
||||||
<variable name="process-count" as="xs:integer"
|
<variable name="process-count" as="xs:integer"
|
||||||
select="count( $processing/* )" />
|
select="count( $processing )" />
|
||||||
|
|
||||||
<choose>
|
<choose>
|
||||||
<!-- if there are no pending symbols left, then we are done; return the
|
<!-- if there are no pending symbols left, then we are done; return the
|
||||||
stack -->
|
stack -->
|
||||||
<when test="$pend-count = 0">
|
<when test="$pend-count = 0">
|
||||||
<sequence select="$stack/*" />
|
<sequence select="$stack" />
|
||||||
</when>
|
</when>
|
||||||
|
|
||||||
|
|
||||||
|
@ -277,9 +275,9 @@
|
||||||
<text>r - </text>
|
<text>r - </text>
|
||||||
<value-of select="$cur/@name" />
|
<value-of select="$cur/@name" />
|
||||||
<text> [s:: </text>
|
<text> [s:: </text>
|
||||||
<value-of select="$stack/preproc:sym/@name" />
|
<value-of select="$stack/@name" />
|
||||||
<text> ::s] [r:: </text>
|
<text> ::s] [r:: </text>
|
||||||
<value-of select="$processing/preproc:sym/@name" />
|
<value-of select="$processing/@name" />
|
||||||
<text>::r]</text>
|
<text>::r]</text>
|
||||||
</with-param>
|
</with-param>
|
||||||
</call-template>
|
</call-template>
|
||||||
|
@ -361,9 +359,9 @@
|
||||||
-->
|
-->
|
||||||
<template match="preproc:sym[ @extern='true' ]" mode="l:depgen-process-sym" priority="5">
|
<template match="preproc:sym[ @extern='true' ]" mode="l:depgen-process-sym" priority="5">
|
||||||
<param name="pending" as="element( preproc:sym )*" />
|
<param name="pending" as="element( preproc:sym )*" />
|
||||||
<param name="stack" as="element( l:sym-stack )" />
|
<param name="stack" as="element( preproc:sym )*" />
|
||||||
<param name="path" as="xs:string" />
|
<param name="path" as="xs:string" />
|
||||||
<param name="processing" as="element( l:pstack )" />
|
<param name="processing" as="element( preproc:sym )*" />
|
||||||
|
|
||||||
<variable name="cur" select="." />
|
<variable name="cur" select="." />
|
||||||
|
|
||||||
|
@ -407,7 +405,7 @@
|
||||||
<text>); pulled in by: </text>
|
<text>); pulled in by: </text>
|
||||||
|
|
||||||
<!-- help the user figure out how this happened -->
|
<!-- help the user figure out how this happened -->
|
||||||
<for-each select="$processing/preproc:sym">
|
<for-each select="$processing">
|
||||||
<if test="position() gt 1">
|
<if test="position() gt 1">
|
||||||
<text> - </text>
|
<text> - </text>
|
||||||
</if>
|
</if>
|
||||||
|
@ -433,7 +431,7 @@
|
||||||
<!-- use the resolved symbol in place of the original extern -->
|
<!-- use the resolved symbol in place of the original extern -->
|
||||||
<apply-templates select="$eresolv-uniq" mode="l:depgen-process-sym">
|
<apply-templates select="$eresolv-uniq" mode="l:depgen-process-sym">
|
||||||
<with-param name="pending" select="$pending" />
|
<with-param name="pending" select="$pending" />
|
||||||
<with-param name="stack" select="$stack" as="element( l:sym-stack )" />
|
<with-param name="stack" select="$stack" />
|
||||||
<with-param name="path" select="$path" />
|
<with-param name="path" select="$path" />
|
||||||
<with-param name="processing" select="$processing" />
|
<with-param name="processing" select="$processing" />
|
||||||
</apply-templates>
|
</apply-templates>
|
||||||
|
@ -443,9 +441,9 @@
|
||||||
<template mode="l:depgen-process-sym" priority="1"
|
<template mode="l:depgen-process-sym" priority="1"
|
||||||
match="preproc:sym">
|
match="preproc:sym">
|
||||||
<param name="pending" as="element( preproc:sym )*" />
|
<param name="pending" as="element( preproc:sym )*" />
|
||||||
<param name="stack" as="element( l:sym-stack )" />
|
<param name="stack" as="element( preproc:sym )*" />
|
||||||
<param name="path" as="xs:string" />
|
<param name="path" as="xs:string" />
|
||||||
<param name="processing" as="element( l:pstack )" />
|
<param name="processing" as="element( preproc:sym )*" />
|
||||||
|
|
||||||
<variable name="cur" as="element( preproc:sym )"
|
<variable name="cur" as="element( preproc:sym )"
|
||||||
select="." />
|
select="." />
|
||||||
|
@ -455,7 +453,7 @@
|
||||||
exception is if the circular dependency is a function, since that simply
|
exception is if the circular dependency is a function, since that simply
|
||||||
implies recursion, which we can handle just fine -->
|
implies recursion, which we can handle just fine -->
|
||||||
<variable name="circ" as="element( preproc:sym )*"
|
<variable name="circ" as="element( preproc:sym )*"
|
||||||
select="$processing/preproc:sym[
|
select="$processing[
|
||||||
@name=$cur/@name
|
@name=$cur/@name
|
||||||
and @src=$cur/@src ]" />
|
and @src=$cur/@src ]" />
|
||||||
|
|
||||||
|
@ -477,7 +475,7 @@
|
||||||
<call-template name="l:depgen-sym">
|
<call-template name="l:depgen-sym">
|
||||||
<with-param name="pending" select="remove( $pending, 1 )" />
|
<with-param name="pending" select="remove( $pending, 1 )" />
|
||||||
<with-param name="processing" select="$processing" />
|
<with-param name="processing" select="$processing" />
|
||||||
<with-param name="stack" select="$stack" as="element( l:sym-stack )" />
|
<with-param name="stack" select="$stack" />
|
||||||
</call-template>
|
</call-template>
|
||||||
</when>
|
</when>
|
||||||
|
|
||||||
|
@ -485,8 +483,7 @@
|
||||||
<!-- process; TODO: good refactoring point; large template -->
|
<!-- process; TODO: good refactoring point; large template -->
|
||||||
<otherwise>
|
<otherwise>
|
||||||
<variable name="existing" as="element( preproc:sym )*"
|
<variable name="existing" as="element( preproc:sym )*"
|
||||||
select="$stack/preproc:sym[
|
select="$stack[ @name=$cur/@name ]" />
|
||||||
@name=$cur/@name ]" />
|
|
||||||
|
|
||||||
<!-- TODO: this uses @name instead of @src because of map import
|
<!-- TODO: this uses @name instead of @src because of map import
|
||||||
paths; decide on one or the other -->
|
paths; decide on one or the other -->
|
||||||
|
@ -518,7 +515,7 @@
|
||||||
<with-param name="pending" select="remove( $pending, 1 )" />
|
<with-param name="pending" select="remove( $pending, 1 )" />
|
||||||
<with-param name="processing" select="$processing" />
|
<with-param name="processing" select="$processing" />
|
||||||
|
|
||||||
<with-param name="stack" as="element( l:sym-stack )">
|
<with-param name="stack" as="element( preproc:sym )*">
|
||||||
<!-- if this symbol already exists on the stack, then there is no use
|
<!-- if this symbol already exists on the stack, then there is no use
|
||||||
re-adding it (note that we check both the symbol name and its source
|
re-adding it (note that we check both the symbol name and its source
|
||||||
since symbols could very well share a name due to exporting rules) -->
|
since symbols could very well share a name due to exporting rules) -->
|
||||||
|
@ -546,19 +543,16 @@
|
||||||
</call-template>
|
</call-template>
|
||||||
</variable>
|
</variable>
|
||||||
|
|
||||||
<l:sym-stack>
|
|
||||||
<!-- process the dependencies (note that this has the effect of
|
<!-- process the dependencies (note that this has the effect of
|
||||||
outputting the existing stack as well, which is why we have
|
outputting the existing stack as well, which is why we have
|
||||||
not yet done so) -->
|
not yet done so) -->
|
||||||
<call-template name="l:depgen-sym">
|
<call-template name="l:depgen-sym">
|
||||||
<with-param name="pending" select="$deps-aug" />
|
<with-param name="pending" select="$deps-aug" />
|
||||||
<with-param name="stack" select="$stack" as="element( l:sym-stack )" />
|
<with-param name="stack" select="$stack" />
|
||||||
<with-param name="path" select="$mypath" />
|
<with-param name="path" select="$mypath" />
|
||||||
<with-param name="processing" as="element( l:pstack )">
|
<with-param name="processing" as="element( preproc:sym )*">
|
||||||
<l:pstack>
|
<sequence select="$processing" />
|
||||||
<sequence select="$processing/*" />
|
|
||||||
<sequence select="$cur" />
|
<sequence select="$cur" />
|
||||||
</l:pstack>
|
|
||||||
</with-param>
|
</with-param>
|
||||||
</call-template>
|
</call-template>
|
||||||
|
|
||||||
|
@ -566,7 +560,6 @@
|
||||||
<preproc:sym>
|
<preproc:sym>
|
||||||
<sequence select="$cur/@*" />
|
<sequence select="$cur/@*" />
|
||||||
</preproc:sym>
|
</preproc:sym>
|
||||||
</l:sym-stack>
|
|
||||||
</when>
|
</when>
|
||||||
|
|
||||||
|
|
||||||
|
@ -760,7 +753,7 @@
|
||||||
<value-of select="concat( $cur/@src, '/', $cur/@name )" />
|
<value-of select="concat( $cur/@src, '/', $cur/@name )" />
|
||||||
<text>): </text>
|
<text>): </text>
|
||||||
|
|
||||||
<for-each select="$stack//preproc:sym">
|
<for-each select="$stack">
|
||||||
<if test="position() > 1">
|
<if test="position() > 1">
|
||||||
<text> - </text>
|
<text> - </text>
|
||||||
</if>
|
</if>
|
||||||
|
|
Loading…
Reference in New Issue