Skip to content
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

refactor: re-implement [Appendable_list] #9050

Merged
merged 10 commits into from
Nov 3, 2023

Conversation

rgrinberg
Copy link
Member

@rgrinberg rgrinberg commented Oct 31, 2023

This is the same as #9033 without any additional book-keeping for empty checks or using the most compact constructors. Performance is looking better now.

@rgrinberg rgrinberg requested a review from snowleopard October 31, 2023 00:43
@rgrinberg rgrinberg force-pushed the appendable-list branch 2 times, most recently from 84cace8 to 8bdb985 Compare October 31, 2023 01:12
@pmwhite
Copy link
Collaborator

pmwhite commented Oct 31, 2023

Looks good to me. I'm not suggesting we put it in this PR, but I'm curious if providing built-in iteration functions for Appendable_list.t would be worthwhile. They would save the extra iteration and allocation that to_list does, but each iteration would probably be more expensive because of all the indirection in the data structure. I guess it depends on how many times we iterate over the list of aliases.

@pmwhite
Copy link
Collaborator

pmwhite commented Oct 31, 2023

Actually, it occurs to me that we can reduce allocation in to_list_rev a bit:

let to_list_rev =
  let rec loop1 acc t stack =
    match t with
    | Empty -> loop0 acc stack
    | Singleton x -> loop0 (x :: acc) stack
    | Cons (x, xs) -> loop1 (x :: acc) xs stack
    | List xs -> loop0 (List.rev_append xs acc) stack
    | Append (xs, ys) -> loop1 acc xs (ys :: stack)   
    | Concat [] -> loop0 acc stack
    | Concat (x :: xs) -> loop1 acc x (Concat xs :: stack)
  and loop0 acc stack =                                 
    match stack with
    | [] -> acc
    | t :: stack -> loop1 acc t stack
  in
  fun t -> loop1 [] t []    
;;

@rgrinberg
Copy link
Member Author

Looks good to me. I'm not suggesting we put it in this PR, but I'm curious if providing built-in iteration functions for Appendable_list.t would be worthwhile. They would save the extra iteration and allocation that to_list does, but each iteration would probably be more expensive because of all the indirection in the data structure. I guess it depends on how many times we iterate over the list of aliases.

One issue that makes this idea less attractive is that we are specifically converting this into a list because the list is a better representation for memoization (uses less space, easy to compare/hash).

@rgrinberg
Copy link
Member Author

Actually, it occurs to me that we can reduce allocation in to_list_rev a bit:

let to_list_rev =
  let rec loop1 acc t stack =
    match t with
    | Empty -> loop0 acc stack
    | Singleton x -> loop0 (x :: acc) stack
    | Cons (x, xs) -> loop1 (x :: acc) xs stack
    | List xs -> loop0 (List.rev_append xs acc) stack
    | Append (xs, ys) -> loop1 acc xs (ys :: stack)   
    | Concat [] -> loop0 acc stack
    | Concat (x :: xs) -> loop1 acc x (Concat xs :: stack)
  and loop0 acc stack =                                 
    match stack with
    | [] -> acc
    | t :: stack -> loop1 acc t stack
  in
  fun t -> loop1 [] t []    
;;

Thanks. I applied this patch.

@rgrinberg
Copy link
Member Author

@pmwhite @snowleopard let me know once this is benchmarked internally.

Copy link
Collaborator

@snowleopard snowleopard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should disentangle the changes to the Appendable_list implementation from the rest of the refactoring, to make it easier to benchmark.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
src/dune_engine/rules.mli Outdated Show resolved Hide resolved
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
_
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
_
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Copy link
Collaborator

@snowleopard snowleopard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I think this one is good to go, though I don't know how our internal benchmarking went.

@snowleopard
Copy link
Collaborator

snowleopard commented Nov 3, 2023

OK, I got some benchmark results for this PR applied internally: it's a consistent but small improvement (0.3-0.4% time, 0.1% memory). Let's merge it.

@pmwhite I'm assuming you're going to import it as part of your feature. (Though it's easy for me to do too since I've got a feature ready.)

@rgrinberg rgrinberg merged commit d727739 into ocaml:main Nov 3, 2023
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants