On Wed, Mar 10, 2010 at 7:22 AM, Stuart Roebuck <stuart.roeb...@gmail.com>wrote:

> Okay, so I now understand what is happening a little better.
>
> When I saw a construct like:
>
>  bind("example",xhtml,
>    "first_name" -> SHtml.text(user.first_name, user.first_name(_)),
>    "last_name" -> SHtml.text(user.last_name, user.last_name(_))
>
> it reminded me of a match with cases and my assumption was that each
> match would only be called if and when the match was found. In reality
> what appears to happen is that the item on the right hand side of the
> "->" is usually evaluated and then placed into a Map with the String
> like "first_name" being the key.
>
>
You're welcome to take up laziness vs. strictness with the EPFL team.
 There's only so much we can do to be lazy and it does take extra syntax
(see Ross's reply).


> So, if every binding is used in every case there is no big issue here,
> but if you have bindings that aren't all used they will none-the-less
> be evaluated every time you try to bind.
>
> Also every time the bind function is called a new Map appears to be
> generated and indexed in memory which doesn't seem as efficient as it
> could be.
>

There's a sign over a urinal in a mens room at Google that reads "Premature
Optimization is the root of all evil."  Now, I think that's an
overstatement, but in this case, it's applicable.

Is there an *actual* problem with building a Map()?  Can you measure the
problem?  Do you have a more efficient solution?

Now, when I wrote that particular code, I was very cognizant of the
performance implications.

The cost of producing the Map() (backed by a HashMap) in the normal case (no
hash collisions) is O(n).  Worst case is O(n log n).

For each element we're binding, we have look up the tag of the node to bind.
 If we are using our Map(), the look-up time is O(1) (or worst case O(log
n)).  If we have n elements that we're binding, the expected cost is O(n)
and worst case is O(n log n).

So, we have an algorithm that normally executes in 2xO(n) and worst case
2xO(n log n).

Now, if we didn't create the Map, we'd have to cycle through the possible
binds and we'd wind up with O(n ^ 2).  Even if you have a PartialFunction
(pattern matching) against strings, it's O(n) to match the pattern.

So, would you rather have an O(n) algorithm that can degrade to O(n log n)
and uses marginally more memory or would you rather have an O(n ^ 2)
algorithm that uses marginally less memory?

And if you're worried about the memory used by the Map(), on pre 1.6 build
16 JVMs, the Map will not likely escape the Eden memory pool (which means
very quick GC).  On the most recent JVMs, the escape analysis should kick in
and the Map and its elements will be allocated on the heap and never be
subject to GC.


>
> I can't help but wonder whether this could be converted to a form of
> match which would then be built at compile time and re-used and would
> only evaluate those matches that matched.
>

In the event that you can create a benchmark and a real-world situation that
actually needs this, please open a ticket.  But, I suspect that even if you
pre-created a Map and passed it into bind(), that the performance would be
nearly identical, but we'd have more public APIs to document which seems to
be something that also annoys you.


>
> In the meantime I see that you can convert the code above to:
>
>  bind("example",xhtml,
>    FuncBindParam("first_name", () => SHtml.text(user.first_name,
> user.first_name(_)),
>    FuncBindParam("last_name", () => SHtml.text(user.last_name,
> user.last_name(_))
>
> to get a form of lazy evaluation.
>
>
> On Mar 10, 11:01 am, Stuart Roebuck <stuart.roeb...@gmail.com> wrote:
> > I've been trying to figure why some binding is giving me a stack
> > overflow and I've discovered that if you use the BindHelpers.bind
> > method with a set of function BindParams, all the functions are
> > evaluated regardless of whether a match is found.
> >
> > So, for example, if you bind to an empty NodeSeq and have a BindParam
> > which will never match like:
> >       "you won't find me here" -> { print("Got here!");
> > NodeSeq.Empty }
> > …you find that the print statement is called.
> >
> > This really surprised me.  Is this intentional behaviour as it seems
> > to be a potential source of significant redundant processing?
> >
> > Stuart.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Lift" group.
> To post to this group, send email to lift...@googlegroups.com.
> To unsubscribe from this group, send email to
> liftweb+unsubscr...@googlegroups.com<liftweb%2bunsubscr...@googlegroups.com>
> .
> For more options, visit this group at
> http://groups.google.com/group/liftweb?hl=en.
>
>


-- 
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics

-- 
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.

Reply via email to