[memcached] goodbye

Summary: Not used feature and with no obvious roadmap anymore.

Reviewed By: jberdine, jvillard

Differential Revision: D17855860

fbshipit-source-id: fd75b9d62
master
Nikos Gorogiannis 5 years ago committed by Facebook Github Bot
parent 765e0bf2f4
commit 432d391a32

@ -1479,13 +1479,6 @@ INTERNAL OPTIONS
--max-nesting-reset --max-nesting-reset
Cancel the effect of --max-nesting. Cancel the effect of --max-nesting.
--memcached
Activates: EXPERIMENTAL: Use memcached caching summaries during
analysis. (Conversely: --no-memcached)
--memcached-size-mb int
EXPERIMENTAL: Default memcached size in megabytes.
--method-decls-info method_decls_info.json --method-decls-info method_decls_info.json
Specifies the file containing the method declarations info (eg. Specifies the file containing the method declarations info (eg.
start line, end line, class, method name, etc.) when Infer is run start line, end line, class, method name, etc.) when Infer is run

@ -42,16 +42,14 @@ let analyze_target : TaskScheduler.target Tasks.doer =
Ondemand.analyze_proc_name_toplevel exe_env proc_name Ondemand.analyze_proc_name_toplevel exe_env proc_name
in in
fun target -> fun target ->
if Config.memcached then Memcached.connect () ;
let exe_env = Exe_env.mk () in let exe_env = Exe_env.mk () in
(* clear cache for each source file to avoid it growing unboundedly *) (* clear cache for each source file to avoid it growing unboundedly *)
clear_caches () ; clear_caches () ;
( match target with match target with
| Procname procname -> | Procname procname ->
analyze_proc_name exe_env procname analyze_proc_name exe_env procname
| File source_file -> | File source_file ->
analyze_source_file exe_env source_file ) ; analyze_source_file exe_env source_file
if Config.memcached then Memcached.disconnect ()
let output_json_makefile_stats clusters = let output_json_makefile_stats clusters =

@ -288,11 +288,3 @@ module OnDisk = struct
in in
Procedures.get_all ~filter () |> List.iter ~f:reset Procedures.get_all ~filter () |> List.iter ~f:reset
end end
module SummaryValue = struct
type nonrec t = t option
let label = "summary"
end
module SummaryServer = Memcached.Make (SummaryValue)

@ -120,7 +120,3 @@ module OnDisk : sig
val dummy : t val dummy : t
(** dummy summary for testing *) (** dummy summary for testing *)
end end
module SummaryValue : Memcached.Value with type t = t option
module SummaryServer : Memcached.Server with module Value = SummaryValue

@ -287,21 +287,6 @@ let create_perf_stats_report source_file =
PerfStats.get_reporter (PerfStats.Backend source_file) () PerfStats.get_reporter (PerfStats.Backend source_file) ()
let hash_procname proc_name = Typ.Procname.to_unique_id proc_name |> Utils.string_crc_hex32
let memcache_get proc_name =
if not Config.memcached then None
else
let key = hash_procname proc_name in
Summary.SummaryServer.get ~key
let memcache_set proc_name summ =
if Config.memcached then
let key = hash_procname proc_name in
Summary.SummaryServer.set ~key summ
let register_callee ?caller_summary callee_pname = let register_callee ?caller_summary callee_pname =
Option.iter Option.iter
~f:(fun (summary : Summary.t) -> ~f:(fun (summary : Summary.t) ->
@ -348,28 +333,22 @@ let analyze_callee ?caller_summary callee =
| Some callee_summary_option -> | Some callee_summary_option ->
callee_summary_option callee_summary_option
| None -> | None ->
let callee_summary_option, update_memcached = let summ_opt =
match memcache_get callee_pname with if callee_should_be_analyzed callee then
| Some summ_opt -> match get_callee_proc_desc callee with
(summ_opt, false) | Some callee_pdesc ->
| None -> Some
if callee_should_be_analyzed callee then (run_proc_analysis
match get_callee_proc_desc callee with ~caller_pdesc:(Option.map ~f:Summary.get_proc_desc caller_summary)
| Some callee_pdesc -> callee_pdesc)
( Some | None ->
(run_proc_analysis Summary.OnDisk.get callee_pname
~caller_pdesc:(Option.map ~f:Summary.get_proc_desc caller_summary) else (
callee_pdesc) EventLogger.log_skipped_pname (F.asprintf "%a" Typ.Procname.pp callee_pname) ;
, true ) Summary.OnDisk.get callee_pname )
| None ->
(Summary.OnDisk.get callee_pname, true)
else (
EventLogger.log_skipped_pname (F.asprintf "%a" Typ.Procname.pp callee_pname) ;
(Summary.OnDisk.get callee_pname, true) )
in in
if update_memcached then memcache_set callee_pname callee_summary_option ; LocalCache.add callee_pname summ_opt ;
LocalCache.add callee_pname callee_summary_option ; summ_opt
callee_summary_option
let analyze_proc_desc ~caller_summary callee_pdesc = let analyze_proc_desc ~caller_summary callee_pdesc =

@ -1738,16 +1738,6 @@ and method_decls_info =
method name, etc.) when Infer is run Test Determinator mode with $(b,--test-determinator)." method name, etc.) when Infer is run Test Determinator mode with $(b,--test-determinator)."
and memcached =
CLOpt.mk_bool ~long:"memcached" ~default:false
"EXPERIMENTAL: Use memcached caching summaries during analysis."
and memcached_size_mb =
CLOpt.mk_int ~long:"memcached-size-mb" ~default:2048
"EXPERIMENTAL: Default memcached size in megabytes."
and merge = and merge =
CLOpt.mk_bool ~deprecated:["merge"] ~long:"merge" CLOpt.mk_bool ~deprecated:["merge"] ~long:"merge"
~in_help:InferCommand.[(Analyze, manual_buck_flavors)] ~in_help:InferCommand.[(Analyze, manual_buck_flavors)]
@ -2994,10 +2984,6 @@ and max_nesting = !max_nesting
and method_decls_info = !method_decls_info and method_decls_info = !method_decls_info
and memcached = !memcached
and memcached_size_mb = !memcached_size_mb
and merge = !merge and merge = !merge
and ml_buckets = !ml_buckets and ml_buckets = !ml_buckets

@ -481,10 +481,6 @@ val loop_hoisting : bool
val max_nesting : int option val max_nesting : int option
val memcached : bool
val memcached_size_mb : int
val merge : bool val merge : bool
val method_decls_info : string option val method_decls_info : string option

@ -1,181 +0,0 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module L = Logging
(** unix socket name, always relative to the master [results_dir] *)
let memcached_socket_relative = "memcached.socket"
(** find the results_dir of the top-level infer process *)
let results_dir = Config.toplevel_results_dir
(** log file for memcached *)
let memcached_log = results_dir ^ "/memcached.log"
(** binary name -- assumed to be on path *)
let memcached_bin = "memcached"
(** shell to use for redirecting memcached's output to the log *)
let shell = "sh"
type server = {input: In_channel.t; output: Out_channel.t}
(** Unix socket *paths* have a historical length limit of ~100 chars (!?*@&*$). However, this only applies
to the argument passed in the system call to create the socket, not to the actual path.
Thus a workaround is to cd into the parent dir of the socket and then use it, hence this function. *)
let in_results_dir ~f = Utils.do_in_dir ~dir:results_dir ~f
let fail_on response_line = L.die InternalError "Unexpected server response: %s" response_line
let send server str = Out_channel.output_string server.output str
let eol = "\r\n"
let send_eol server = send server eol
let flush_server server = Out_channel.flush server.output
let send_line server str = send server str ; send_eol server ; flush_server server
let recv_line server =
match In_channel.input_line ~fix_win_eol:true server.input with
| None ->
fail_on "No response"
| Some line ->
line
let expect_line server lines =
match recv_line server with
| x when List.exists lines ~f:(String.equal x) ->
()
| response ->
fail_on response
(** socket to memcached server *)
let server : server option ref = ref None
let with_server ~f =
match !server with
| None ->
L.die InternalError "Asked to perform socket operation without live connection.@."
| Some s ->
f s
let disconnect () =
with_server ~f:(fun s ->
server := None ;
Unix.shutdown_connection s.input ;
(* For some reason the below sometimes throws -- wrong docs? *)
(* In_channel.close s.input ; *)
Out_channel.close s.output )
let connect () =
if Option.is_some !server then
L.die InternalError "Asked to connect memcached while already connected.@." ;
in_results_dir ~f:(fun () ->
let input, output = Unix.open_connection (ADDR_UNIX memcached_socket_relative) in
server := Some {input; output} )
let stats server =
let rec aux acc = match recv_line server with "END" -> List.rev acc | l -> aux (l :: acc) in
send_line server "stats" ; aux []
let stop pid () =
connect () ;
let stats = with_server ~f:stats in
disconnect () ;
Signal.send Signal.term (`Pid pid) |> ignore ;
Unix.wait (`Pid pid) |> ignore ;
in_results_dir ~f:(fun () -> Unix.remove memcached_socket_relative) ;
Out_channel.(with_file memcached_log ~append:true ~f:(fun ch -> output_lines ch stats))
let start () =
let socket_exists () =
in_results_dir ~f:(fun () -> Sys.file_exists_exn memcached_socket_relative)
in
if Option.is_some !server then
L.die InternalError "Connection is open but asked to start memcached.@." ;
(* Unix sockets can be shadowed, so avoid creating a new socket/server if there is one already *)
if socket_exists () then ()
else
let verbosity = match Config.debug_level_analysis with 0 -> "" | 1 -> "-v" | _ -> "-vv" in
let cmd =
Printf.sprintf "exec %s %s -Bascii -C -m%d -s%s > %s 2>&1" memcached_bin verbosity
Config.memcached_size_mb memcached_socket_relative memcached_log
in
let pid = in_results_dir ~f:(Unix.fork_exec ~prog:shell ~argv:[shell; "-c"; cmd]) in
(* Wait until socket is open -- NB this waits for 0.05s not 0.05ns *)
while not (socket_exists ()) do
Unix.nanosleep 0.05 |> ignore
done ;
Epilogues.register ~description:"Shutdown Memcached daemon" ~f:(stop pid)
module type Value = sig
type t
val label : string
end
module type Server = sig
module Value : Value
val get : key:string -> Value.t option
val set : key:string -> Value.t -> unit
end
module Make (V : Value) : Server with module Value = V = struct
module Value = V
let set_ =
let buffer = ref (Bytes.create 1024) in
let rec try_to_buffer value =
try Marshal.to_buffer !buffer 0 (Bytes.length !buffer) value []
with Failure _ ->
(* double buffer length *)
buffer := Bytes.create (2 * Bytes.length !buffer) ;
try_to_buffer value
in
fun server ~key value ->
let value_length = try_to_buffer value in
Printf.fprintf server.output "set %s:%s 0 0 %d%s" Value.label key value_length eol ;
Out_channel.output server.output ~buf:!buffer ~pos:0 ~len:value_length ;
send_eol server ;
flush_server server ;
expect_line server ["STORED"; "SERVER_ERROR object too large for cache"]
let get_ server ~key =
Printf.fprintf server.output "get %s:%s%s" Value.label key eol ;
flush_server server ;
let value_line = recv_line server in
match String.split value_line ~on:' ' with
| ["END"] ->
None
| ["VALUE"; _key'; _flags; _bytes] ->
let value : Value.t = Marshal.from_channel server.input in
(* eat up the trailing eol *)
expect_line server [""] ;
expect_line server ["END"] ;
Some value
| _ ->
fail_on value_line
let get ~key = with_server ~f:(get_ ~key)
(* TODO: do this on background thread to avoid blocking on the response *)
let set ~key value = with_server ~f:(fun s -> set_ s ~key value)
end

@ -1,39 +0,0 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
(** Interface for managing a (single) memcached daemon and getting/setting OCaml values *)
val connect : unit -> unit
(** connect to a running memcached server -- only call this from processes which do not fork *)
val disconnect : unit -> unit
(** disconnect after having connected first *)
val start : unit -> unit
(** start a memcached daemon and set up an epilogue to kill it on exit -- only for top-level *)
(** type to marshal, plus a unique label that will be colon-prepended to a key,
roughly signifying a table *)
module type Value = sig
type t
val label : string
end
module type Server = sig
module Value : Value
val get : key:string -> Value.t option
(** get a value, [None] means no [key] exists *)
val set : key:string -> Value.t -> unit
(** set a [key]/value pair. NB we swallow failures due to exceeding max value size currently.
This will need to be changed before memcached is used as a primary store. *)
end
module Make (V : Value) : Server with module Value = V

@ -63,10 +63,7 @@ let setup () =
| Events -> | Events ->
ResultsDir.assert_results_dir "have you run infer before?" ) ; ResultsDir.assert_results_dir "have you run infer before?" ) ;
db_start () ; db_start () ;
if CLOpt.is_originator then ( if CLOpt.is_originator then ( RunState.add_run_to_sequence () ; RunState.store () ) ;
RunState.add_run_to_sequence () ;
RunState.store () ;
if Config.memcached then Memcached.start () ) ;
() ()

Loading…
Cancel
Save