On 2.8 ordinary snippets get instantiated a few times
A diff of the stack traces seems to reveal the problem:
At LiftSession.scala:909, def locateAndCacheSnippet calls ListHelpers.first with a function that potentially instantiates the snippet. Then first creates a view from the parameter 'in' and flatMaps the resulting view using that function which when called may instantiate the class. However that function is called multiple times, since every call to isEmpty is delegated to IterableViewLike's iterator, which is created each time anew, reevaluating the flatmapping function.
Changing the code to the following fixed the problem:
def locateAndCacheSnippet(tagName: String): Box[AnyRef] =
snippetMap.is.get(tagName) or {
val tmp = scala.collection.mutable.HashMap[String,Box[AnyRef]]()
first(LiftRules.snippetNamesToSearch.vend(tagName)) { nameToTry =>
tmp.getOrElseUpdate(nameToTry, {
val ret = LiftRules.snippet(nameToTry) or findSnippetInstance(nameToTry)
ret.foreach(s => snippetMap.set(snippetMap.is.update(tagName, s)))
ret
})
}
}
Note that my local repository is not 100% up to date so I marked the changes in bold.
Here are the relevant slices of the stack traces:
ONCE:
at java.lang.Class.newInstance(Class.java:308)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$instantiateOrRedirect$1.apply(LiftSession.scala:756)
at net.liftweb.util.ControlHelpers$class.tryo(ControlHelpers.scala:67)
at net.liftweb.util.Helpers$.tryo(Helpers.scala:34)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$instantiateOrRedirect(LiftSession.scala:752)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.common.Full.flatMap(Box.scala:400)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:818)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:909)
at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:48)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.Iterator$$anon$21.hasNext(Iterator.scala:405)
at scala.collection.IterableLike$class.isEmpty(IterableLike.scala:92)
at scala.collection.SeqViewLike$$anon$4.isEmpty(SeqViewLike.scala:176)
at scala.collection.TraversableLike$class.headOption(TraversableLike.scala:483)
at scala.collection.SeqViewLike$$anon$4.headOption(SeqViewLike.scala:176)
at net.liftweb.util.ListHelpers$class.first(ListHelpers.scala:56)
at net.liftweb.util.Helpers$.first(Helpers.scala:34)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
TWICE:
at java.lang.Class.newInstance(Class.java:308)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$instantiateOrRedirect$1.apply(LiftSession.scala:756)
at net.liftweb.util.ControlHelpers$class.tryo(ControlHelpers.scala:67)
at net.liftweb.util.Helpers$.tryo(Helpers.scala:34)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$instantiateOrRedirect(LiftSession.scala:752)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.common.Full.flatMap(Box.scala:400)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:818)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:909)
at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:48)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.Iterator$$anon$21.hasNext(Iterator.scala:405)
at scala.collection.IterableLike$class.isEmpty(IterableLike.scala:92)
at scala.collection.SeqViewLike$$anon$4.isEmpty(SeqViewLike.scala:176)
at scala.collection.IterableLike$class.head(IterableLike.scala:101)
at scala.collection.SeqViewLike$$anon$4.head(SeqViewLike.scala:176)
at scala.collection.TraversableLike$class.headOption(TraversableLike.scala:483)
at scala.collection.SeqViewLike$$anon$4.headOption(SeqViewLike.scala:176)
at net.liftweb.util.ListHelpers$class.first(ListHelpers.scala:56)
at net.liftweb.util.Helpers$.first(Helpers.scala:34)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
THREE TIMES:
at java.lang.Class.newInstance(Class.java:308)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$instantiateOrRedirect$1.apply(LiftSession.scala:756)
at net.liftweb.util.ControlHelpers$class.tryo(ControlHelpers.scala:67)
at net.liftweb.util.Helpers$.tryo(Helpers.scala:34)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$instantiateOrRedirect(LiftSession.scala:752)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.common.Full.flatMap(Box.scala:400)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:818)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:909)
at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:48)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.Iterator$$anon$21.hasNext(Iterator.scala:405)
at scala.collection.Iterator$$anon$21.next(Iterator.scala:406)
at scala.collection.IterableLike$class.head(IterableLike.scala:102)
at scala.collection.SeqViewLike$$anon$4.head(SeqViewLike.scala:176)
at scala.collection.TraversableLike$class.headOption(TraversableLike.scala:483)
at scala.collection.SeqViewLike$$anon$4.headOption(SeqViewLike.scala:176)
at net.liftweb.util.ListHelpers$class.first(ListHelpers.scala:56)
at net.liftweb.util.Helpers$.first(Helpers.scala:34)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
Thanks.
At LiftSession.scala:909, def locateAndCacheSnippet calls ListHelpers.first with a function that potentially instantiates the snippet. Then first creates a view from the parameter 'in' and flatMaps the resulting view using that function which when called may instantiate the class. However that function is called multiple times, since every call to isEmpty is delegated to IterableViewLike's iterator, which is created each time anew, reevaluating the flatmapping function.
Changing the code to the following fixed the problem:
def locateAndCacheSnippet(tagName: String): Box[AnyRef] =
snippetMap.is.get(tagName) or {
val tmp = scala.collection.mutable.HashMap[String,Box[AnyRef]]()
first(LiftRules.snippetNamesToSearch.vend(tagName)) { nameToTry =>
tmp.getOrElseUpdate(nameToTry, {
val ret = LiftRules.snippet(nameToTry) or findSnippetInstance(nameToTry)
ret.foreach(s => snippetMap.set(snippetMap.is.update(tagName, s)))
ret
})
}
}
Note that my local repository is not 100% up to date so I marked the changes in bold.
Here are the relevant slices of the stack traces:
ONCE:
at java.lang.Class.newInstance(Class.java:308)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$instantiateOrRedirect$1.apply(LiftSession.scala:756)
at net.liftweb.util.ControlHelpers$class.tryo(ControlHelpers.scala:67)
at net.liftweb.util.Helpers$.tryo(Helpers.scala:34)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$instantiateOrRedirect(LiftSession.scala:752)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.common.Full.flatMap(Box.scala:400)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:818)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:909)
at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:48)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.Iterator$$anon$21.hasNext(Iterator.scala:405)
at scala.collection.IterableLike$class.isEmpty(IterableLike.scala:92)
at scala.collection.SeqViewLike$$anon$4.isEmpty(SeqViewLike.scala:176)
at scala.collection.TraversableLike$class.headOption(TraversableLike.scala:483)
at scala.collection.SeqViewLike$$anon$4.headOption(SeqViewLike.scala:176)
at net.liftweb.util.ListHelpers$class.first(ListHelpers.scala:56)
at net.liftweb.util.Helpers$.first(Helpers.scala:34)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
TWICE:
at java.lang.Class.newInstance(Class.java:308)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$instantiateOrRedirect$1.apply(LiftSession.scala:756)
at net.liftweb.util.ControlHelpers$class.tryo(ControlHelpers.scala:67)
at net.liftweb.util.Helpers$.tryo(Helpers.scala:34)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$instantiateOrRedirect(LiftSession.scala:752)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.common.Full.flatMap(Box.scala:400)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:818)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:909)
at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:48)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.Iterator$$anon$21.hasNext(Iterator.scala:405)
at scala.collection.IterableLike$class.isEmpty(IterableLike.scala:92)
at scala.collection.SeqViewLike$$anon$4.isEmpty(SeqViewLike.scala:176)
at scala.collection.IterableLike$class.head(IterableLike.scala:101)
at scala.collection.SeqViewLike$$anon$4.head(SeqViewLike.scala:176)
at scala.collection.TraversableLike$class.headOption(TraversableLike.scala:483)
at scala.collection.SeqViewLike$$anon$4.headOption(SeqViewLike.scala:176)
at net.liftweb.util.ListHelpers$class.first(ListHelpers.scala:56)
at net.liftweb.util.Helpers$.first(Helpers.scala:34)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
THREE TIMES:
at java.lang.Class.newInstance(Class.java:308)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$instantiateOrRedirect$1.apply(LiftSession.scala:756)
at net.liftweb.util.ControlHelpers$class.tryo(ControlHelpers.scala:67)
at net.liftweb.util.Helpers$.tryo(Helpers.scala:34)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$instantiateOrRedirect(LiftSession.scala:752)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1$$anonfun$apply$51.apply(LiftSession.scala:819)
at net.liftweb.common.Full.flatMap(Box.scala:400)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:819)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:818)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61$$anonfun$22.apply(LiftSession.scala:910)
at net.liftweb.common.EmptyBox.or(Box.scala:467)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:910)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$61.apply(LiftSession.scala:909)
at scala.Function1$$anonfun$andThen$1.apply(Function1.scala:48)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.IterableViewLike$FlatMapped$$anonfun$iterator$1.apply(IterableViewLike.scala:52)
at scala.collection.Iterator$$anon$21.hasNext(Iterator.scala:405)
at scala.collection.Iterator$$anon$21.next(Iterator.scala:406)
at scala.collection.IterableLike$class.head(IterableLike.scala:102)
at scala.collection.SeqViewLike$$anon$4.head(SeqViewLike.scala:176)
at scala.collection.TraversableLike$class.headOption(TraversableLike.scala:483)
at scala.collection.SeqViewLike$$anon$4.headOption(SeqViewLike.scala:176)
at net.liftweb.util.ListHelpers$class.first(ListHelpers.scala:56)
at net.liftweb.util.Helpers$.first(Helpers.scala:34)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
at net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1.apply(LiftSession.scala:909)
Thanks.
Leave a comment
on 2010-07-28 21:16 *
By dchenbecker
Shouldn't this:
ret.foreach(s => snippetMap.set(snippetMap.is.update(tagName, s)))
be updating the per-request snippetMap? Interestingly, I ran my Lift test project against both the 2.7.7 and 2.8.0 versions of 2.1-SNAPSHOT and only the 2.8.0 code does the multiple instantiation. I wonder if we've run into some change in the collections library that's affecting us.
ret.foreach(s => snippetMap.set(snippetMap.is.update(tagName, s)))
be updating the per-request snippetMap? Interestingly, I ran my Lift test project against both the 2.7.7 and 2.8.0 versions of 2.1-SNAPSHOT and only the 2.8.0 code does the multiple instantiation. I wonder if we've run into some change in the collections library that's affecting us.
High priority for Scala 2.8.0 branch
This appears to be an issue with changes in the behavior of projections in the Scala collections classes. Per Derek Williams (and originally Daniel Sobral) on the scala mailing list, the non-strict view/projection will execute a transform function on every "touch" of an element. What we really want is a Stream version, which can be obtained via the toStream method.
on 2010-07-30 01:32 *
By dchenbecker
Related association with ticket #607 was added
(In revision:ced4f54eb5a160f7b4429b952bbd9355d2ff7ae1) Fix multiple snippet instantiation under Scala 2.8.0
Closes #596
Changes in the collections library for Scala 2.8.0 seem to
have modified behavior of the projection/view methods. Changing
to toStream appears to correct the behavior.
Branch: master
Closes #596
Changes in the collections library for Scala 2.8.0 seem to
have modified behavior of the projection/view methods. Changing
to toStream appears to correct the behavior.
Branch: master
on 2010-07-30 02:45 *
By dchenbecker
Pushed to master and 2.x-2.8_devel