-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make the Lazy basic implementation much faster... #2
base: master
Are you sure you want to change the base?
Commits on Jan 29, 2017
-
Make the Lazy basic implementation much faster...
The current JavaScript Native "memoize" function works by returning a nested forcer function when the outer "memoize" function is called to initialize the representation of the `Lazy' type with the thunk argument so that the evaluated data will later be stored as a local variable within the outer "memoize" function's scope when the returned inner forcer function is called. This scheme of bulding a new nested inner function "on-the-fly" every time a new `Lazy' is initialized is very costly in execution time when run on many current main stream browsers such as Chome 55: http://jsperf.com/iifes-vs-nested-functions/4. In order to speed this up, the generic `Lazy' type is changed to an Elm Tagged Union so that the `force' function can call the Native JS "memoize" function on that type without needing to create any new functions. As an added benefit, the Native JS "memoize" function can check for recursive evaluation of the thunk and throw an error early rather than waiting for a stack overflow on the infinite loop with very little cost in execution time. This change affects the `Lazy a' generic type, the `lazy' type constructor function, and the `force' function as well as the Native JS "memoize" function; howeverk it makes no changes to the API of the Lazy library module. This speed can be verified by timing the enumeration of the following simple natural number lazy list sequence producing function as per the following code: type List a = Node a (Lazy (List a)) nat32s : () -> List Int nat32s() = let nat32si n = Node n << lazy <| \() -> nat32si (n + 1) in nat32si 0 nthnat32 : Int -> String nthnat32 n = let nthnati n nts = case nts of Node _ tl -> if n <= 0 then case nts of Node hd _ -> toString hd else nthnati (n - 1) (force tl) in nthnati n (nat32s()) When run using the proposed changes compared to with the original code, running `nthnat32 999999' (one million iterations) is faster by about six times for Chrome 55 Stable, about four times for Firefox 51 Stable, and about two times faster for Microsoft Edge 38.14393.0.0, with all three browsers having about the same overall exectution time after the change (Chrome was formerly considerably slower than the others). The version number has only been upped to 2.1.0 although this is a very significant change as there are no changes to the API.
Configuration menu - View commit details
-
Copy full SHA for a5c8cd5 - Browse repository at this point
Copy the full SHA a5c8cd5View commit details -
Merge pull request #1 from GordonBGood/make-faster
Make the Lazy basic implementation much faster...
Configuration menu - View commit details
-
Copy full SHA for b69e292 - Browse repository at this point
Copy the full SHA b69e292View commit details
Commits on Jan 30, 2017
-
Once the Lazy type is based on a Tagged Union, it is then advantageous to have a `lazyFromValue` function added to the API so that when an immediately evaluated value that does not need to be deferred is desired, one can create it with this function. The result is that one level of extra function call to `force` the evaluation is not required when this function is used.
Configuration menu - View commit details
-
Copy full SHA for bb44d87 - Browse repository at this point
Copy the full SHA bb44d87View commit details
Commits on Jan 31, 2017
-
Correct example & docs for lazyFromValue
Corrected example and simplified documentation to reflect a simple use case.
Configuration menu - View commit details
-
Copy full SHA for ba80812 - Browse repository at this point
Copy the full SHA ba80812View commit details -
Corrected example & added note for `andThen'...
The previous example was incorrect as to use of arguments for the `cons` function and naming of an argument and non-matching braces for the `append' function; the example code as also been tuned with an inner "wrapper" to reduce the number of arguments. A note was also added to remind users that this required way of implementing lazy lists inside a `Lazy' wrapper isn't as efficient as non-wrapped due to the many levels of function calls including force/thunk/lazy function calls/compositions required, but that an implementation such as this is required to avoid "The Halting Problem" for creating and use of infinite lazy lists inside a `Lazy' wrapper.
Configuration menu - View commit details
-
Copy full SHA for 85f03ee - Browse repository at this point
Copy the full SHA 85f03eeView commit details
Commits on Feb 1, 2017
-
revert manual version change...
I didn't realize where versions were set.
Configuration menu - View commit details
-
Copy full SHA for 9a788c2 - Browse repository at this point
Copy the full SHA 9a788c2View commit details -
Calling JavaScript Native functions as necessary to support the JavaScript Closure Pattern used to hide mutation from Elm, while at the same time allowing the lazyFromValue call and early recursive evaluation detection (throwing an exception if detected).
Configuration menu - View commit details
-
Copy full SHA for 0b72fe5 - Browse repository at this point
Copy the full SHA 0b72fe5View commit details -
Native support for hiding mutation...
Using the JavaScript Closure pattern to hide internal mutation, while as the same time detecting recursive evaluation (failing with an exception if detected) and allowing for the use of the lazyFromValue function to avoid unnecessary deferred evaluation for simple values. Using the "memoize" function from within a Immediately Invoked Function Expression (IIFE) helped with execution speed, in particular on Chrome V8 after many recursions where it seems that some cache/storage overflows and what optimization there is fails.
Configuration menu - View commit details
-
Copy full SHA for a985025 - Browse repository at this point
Copy the full SHA a985025View commit details
Commits on Feb 2, 2017
-
Make the inner forcer function as fast as possible when the value has already been evaluated by re-ordering the conditional checks.
Configuration menu - View commit details
-
Copy full SHA for 05444b8 - Browse repository at this point
Copy the full SHA 05444b8View commit details
Commits on Feb 3, 2017
-
add shared
fix' point function for
Lazy'...This function is a version that uses `Lazy' in its implementation so that it enjoys the recursive evaluation checks introduced with the previous changes. It forms a recursion on a binding, which can also otherwise be done with a simple anonymous function but without the checks. This version does not require a recursion limit condition internal to the function argument as the deferred execution ensures that it can not run away indefinitely.
Configuration menu - View commit details
-
Copy full SHA for 7178139 - Browse repository at this point
Copy the full SHA 7178139View commit details
Commits on Feb 22, 2017
-
Configuration menu - View commit details
-
Copy full SHA for 8d9f7da - Browse repository at this point
Copy the full SHA 8d9f7daView commit details
Commits on Mar 17, 2017
-
Fixed error in type definition...
Missed a correction to the type such that the main file will not compile.
Configuration menu - View commit details
-
Copy full SHA for 92566b4 - Browse repository at this point
Copy the full SHA 92566b4View commit details