On Monday, 7 January 2019 01:03:16 UTC+5:30, Paul deGrandis wrote:
>
> Hi Shantanu,
>
> Interesting project and congrats on the release!
>
> I think Alan was asking more about the runtime and space complexities.  
> What is the core approach used in Calfpath?  What is the runtime and space 
> complexity?  What are the ideal operational conditions and under what 
> conditions does it suffer?  What were the trade-offs made in the approach?
>
> I'm curious to know the answers myself.  Thanks!
>


Hi Paul,

Thanks for expanding Alan's question. I think, the short answer about 
runtime and space complexity would be O(n) and O(n) in Calfpath. Please 
read on for more details. The top performing implementations in Calfpath 
cannot support a very large number of routes (subject to Java method size 
limit.)

At the grass root level, the URI matching code (hand coded in Java, not 
using any regex) is common across all Calfpath routing. It pre-compiles a 
URI pattern, e.g. "/foo/:id/bar" into a vector of tokens ["/foo" :id 
"/bar"] and later the URI-matching function iterates over the tokens.

There are three implementations of routing supported in Calfpath, each of 
which returns `nil` as soon as it realises a match is not likely:

1. Macros: There are macros (in calfpath.core ns) for matching URI, method 
etc. that expand in-line. The URI, method etc are literals that are 
pre-compiled for efficient matching. Obviously, this approach leads to 
in-lined code that runs the risk of exceeding the Java method size (in 
bytecodes) limit for a large number of routes. However, given that the vast 
majority of applications have < 50 routes in number, it is not a concern 
for many.

2. Walking precompiled routes: This is an implementation (in calfpath.route 
ns) of data driven, potentially nested, routes (vector of maps). The routes 
are pre-compiled to a substrate form, still as vector of maps, that a 
function iterates over recursively where nested. This is a simple, 
iterative implementation that can also handle a large number of routes. It 
is also the slowest among the three routing implementations.

3. Loop-unrolled expression tree: This is also an implementation (in 
calfpath.route ns) of data driven, potentially nested, routes (vector of 
maps). The routes are pre-compiled to a substrate form like in the second 
implementation. Then, a function assembles an expression tree using all the 
routes info, wraps it in a function form and calls `eval` to turn the 
expression tree into a function. The result is an in-lined function that 
performs close to the first macro-based implementation, and runs the same 
risk of exceeding Java method size limit for a large number of routes. This 
technique also makes optional (enabled by default) use of deep 
expression-tree building, where pre-compiling URI matching and method 
matching also emit expressions in addition to matcher functions.

In general, the optimisations in Calfpath rely more on JIT's instruction 
caching than data-cache coherence, and the fact that web-routing is such a 
repeatedly executed code that it's OK to inline most of the routing code 
together. Hope this explains Calfpath's approach. Please let me know if you 
have any other questions.


Shantanu
 

>
> Cheers,
> Paul
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to