-
Notifications
You must be signed in to change notification settings - Fork 88
Seq optimization #965
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
Seq optimization #965
Conversation
…def_exc_widen_by_join
Also split config value records into multiple smaller records
…analyzer into int-domain-code-optimizations
jerhard
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, thanks for your pull request!
Good to see that you could find places where it looks like it makes sense to introduce Seq!
I left some comments, mainly about the case when only one operation on a list is replaced by an operation on Seq, and some conversion back and forth (from and to lists) is done. I would assume that in such cases, there would be no performance benefit of doing this, as still the same number of allocations has to be done to create the result list -- only in List.of_seq instead of, say List.map.
| opam update | ||
| # Note: the `--update-invariant` option is needed for replacement of the previous ocaml compiler switch invariant of Goblint | ||
| opam switch -y create . --deps-only ocaml-variants.4.14.0+options ocaml-option-flambda --locked --update-invariant | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these changes necessary or already subsumed by the merged flambda PR?
| **************************************************************************) | ||
|
|
||
| let is_privglob v = GobConfig.get_bool "annotation.int.privglobs" && v.vglob | ||
| let is_privglob v = get_bool "annotation.int.privglobs" && v.vglob |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change in indentation intentional?
src/analyses/base.ml
Outdated
| (* Return the list of elements that have been visited. *) | ||
| if M.tracing then M.traceu "reachability" "All reachable vars: %a\n" AD.pretty !visited; | ||
| List.map AD.singleton (AD.elements !visited) | ||
| List.of_seq @@ (Seq.map AD.singleton) @@ List.to_seq (AD.elements !visited) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since there is only operation (List.map) that is replaced, can one hope that this change actually has a positive performance impact?
src/analyses/base.ml
Outdated
| | (e1, e2) :: eqs -> | ||
| let eqs_for_all_mem e = List.for_all (fun (e1, e2) -> CilType.Exp.(equal e1 e || equal e2 e)) eqs in | ||
| let eqs_map_remove e = List.map (fun (e1, e2) -> if CilType.Exp.equal e1 e then e2 else e1) eqs in | ||
| let eqs_map_remove e = List.of_seq @@ Seq.map (fun (e1, e2) -> if CilType.Exp.equal e1 e then e2 else e1) @@ List.to_seq eqs in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above, as there is only a List.map that is replaced.
src/analyses/base.ml
Outdated
| let* (e, es) = find_common eqs in | ||
| let v = eval_rv a gs st e in (* value of common exp *) | ||
| let vs = List.map (eval_rv a gs st) es in (* values of other sides *) | ||
| let vs = List.of_seq @@ (Seq.map (eval_rv a gs st)) @@ List.to_seq es in (* values of other sides *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above, as there is only a List.map that is replaced.
src/analyses/base.ml
Outdated
| match arg with | ||
| | Some x -> [x] | ||
| | None -> List.map (fun x -> MyCFG.unknown_exp) fd.sformals | ||
| | None -> List.of_seq @@ Seq.map (fun x -> MyCFG.unknown_exp) @@ List.to_seq fd.sformals |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above, as there is only a List.map that is replaced.
src/analyses/base.ml
Outdated
| List.filter_map (create_thread (Some (Mem id, NoOffset)) (Some ptc_arg)) start_funvars_with_unknown | ||
| end | ||
| | _, _ when get_bool "sem.unknown_function.spawn" -> | ||
| | _, _ when get_bool "sem.unknown_function.spawn" -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change in indentation intentional?
src/analyses/base.ml
Outdated
| in | ||
| let forks = forkfun ctx lv f args in | ||
| if M.tracing then if not (List.is_empty forks) then M.tracel "spawn" "Base.special %s: spawning functions %a\n" f.vname (d_list "," d_varinfo) (List.map BatTuple.Tuple3.second forks); | ||
| if M.tracing then if not (List.is_empty forks) then M.tracel "spawn" "Base.special %s: spawning functions %a\n" f.vname (d_list "," d_varinfo) (List.of_seq @@ Seq.map BatTuple.Tuple3.second @@ List.to_seq forks); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above, as there is only a List.map that is replaced.
src/analyses/base.ml
Outdated
| begin match eval_rv (Analyses.ask_of_ctx ctx) gs st id with | ||
| | `Thread a -> | ||
| let v = List.fold VD.join (VD.bot ()) (List.map (fun x -> G.thread (ctx.global (V.thread x))) (ValueDomain.Threads.elements a)) in | ||
| let v = List.fold VD.join (VD.bot ()) (List.of_seq @@ Seq.map (fun x -> G.thread (ctx.global (V.thread x))) @@ List.to_seq (ValueDomain.Threads.elements a)) in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question as above, as there is only a List.map that is replaced.
| (* This is a container variable for holding the config value of ana.int.interval_threshold_widening *) | ||
| (* let interval_threshold_widening_ref: float_precision option ref = ref None | ||
|
|
||
| let get_interval_threshold_widening_ref (): float_precision option = | ||
| if !interval_threshold_widening_ref = None then | ||
| let config_value = Some (get_bool "ana.int.interval_threshold_widening") in | ||
| interval_threshold_widening_ref := config_value; !interval_threshold_widening_ref | ||
| else | ||
| !interval_threshold_widening_ref | ||
|
|
||
| let extract_from_option (x: float_precision option): float_precision = | ||
| match x with | ||
| | None -> failwith "Config option not read" | ||
| | Some x -> x | ||
| *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the blocks of commented code (here and below). Any changes related to the configuration should be separated out.
|
As we discussed I removed all the Seq that are performed on only one single List operation. |
|
Closing in favor of #975. |
We replaced certain List methods with Seq package.
The sanity check passed without errors using make test and the benchmarking using the following flags:
./goblint ../bench/coreutils/ls_comb.c --set pre.cppflags[+] "--std=gnu89" --disable ana.base.context.non-ptr --disable ana.int.def_exc --disable sem.unknown_function.spawn --set ana.thread.domain plain --enable exp.earlyglobs --set ana.base.privatization none --set pre.cppflags[+] -DGOBLINT_NO_BSEARCH --set pre.cppflags[+] -DGOBLINT_NO_ASSERT --set result json-messages --set ana.activated "['base', 'mallocWrapper']" --set ana.ctx_insens[+] base --set ana.ctx_insens[+] mallocWrapper --enable dbg.timing.enabled --enable ana.int.interval --enable ana.int.interval_threshold_wideningOn my local machine the Seq implementation took 820.1s.
We will choose between the Seq and iter packages, which one is better based on the results of the benchmarking on the cluster that you can find in the Iter PR #964.