Summary: We stopped relying on an external perf data file to determine which functions are on the cold start. Let's remove this issue now. NB: Keeping the `--perf-profiler-data-file` as deprecated to prevent issues on the CI and prod. Reviewed By: skcho Differential Revision: D21594150 fbshipit-source-id: faa58782dmaster
parent
8a0d584121
commit
4f97296e55
@ -1,100 +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
|
||||
|
||||
module PerfProfilerDataMap = Caml.Map.Make (struct
|
||||
type t = Procname.t
|
||||
|
||||
let compare = Procname.compare
|
||||
end)
|
||||
|
||||
let global_perf_profiler_data : Perf_profiler_t.perf_profiler_item PerfProfilerDataMap.t ref =
|
||||
ref PerfProfilerDataMap.empty
|
||||
|
||||
|
||||
let split_class_method_name =
|
||||
let class_sep = String.Search_pattern.create "::" in
|
||||
fun qualified_method_name ->
|
||||
match String.Search_pattern.index class_sep ~in_:qualified_method_name with
|
||||
| Some class_sep_pos ->
|
||||
let class_name =
|
||||
String.sub qualified_method_name ~pos:0 ~len:class_sep_pos
|
||||
|> String.tr ~target:'/' ~replacement:'.'
|
||||
in
|
||||
let method_name =
|
||||
let prefix_len = class_sep_pos + 2 in
|
||||
String.sub qualified_method_name ~pos:prefix_len
|
||||
~len:(String.length qualified_method_name - prefix_len)
|
||||
in
|
||||
Some (class_name, method_name)
|
||||
| _ ->
|
||||
None
|
||||
|
||||
|
||||
let pp_perf_profiler_item itm =
|
||||
let open Perf_profiler_t in
|
||||
L.(debug Analysis Medium)
|
||||
"@\n\n\
|
||||
\ [Perf Profiler Log] Function: '%s' @\n\
|
||||
\ count trace id = %i @\n\
|
||||
\ sum inclusive cpu time = %f@\n\
|
||||
\ avg inclusive time = %f @\n\
|
||||
\ sum exclusive cpu time = %f @\n\
|
||||
\ avg exclusive_time = %f @\n"
|
||||
itm.function_name itm.approx_count_trace_id itm.sum_inclusive_cpu_time
|
||||
itm.avg_inclusive_cpu_time_ms itm.sum_exclusive_cpu_time itm.avg_exclusive_cpu_time_ms
|
||||
|
||||
|
||||
let _read_file_perf_data fname =
|
||||
let perf_profiler_data_str =
|
||||
match Utils.read_file fname with
|
||||
| Ok l ->
|
||||
List.map ~f:Perf_profiler_j.perf_profiler_of_string l
|
||||
| Error error ->
|
||||
L.user_error "Failed to read file '%s': %s@." fname error ;
|
||||
[]
|
||||
in
|
||||
let do_item itm =
|
||||
pp_perf_profiler_item itm ;
|
||||
match split_class_method_name itm.Perf_profiler_t.function_name with
|
||||
| Some (classname, methodname) ->
|
||||
let procname = JProcname.make_void_signature_procname ~classname ~methodname in
|
||||
global_perf_profiler_data := PerfProfilerDataMap.add procname itm !global_perf_profiler_data
|
||||
| _ ->
|
||||
()
|
||||
in
|
||||
List.iter ~f:(fun items -> List.iter ~f:do_item items) perf_profiler_data_str
|
||||
|
||||
|
||||
let read_file_flag = ref false
|
||||
|
||||
let prepare_perf_data fname =
|
||||
if not !read_file_flag then (
|
||||
_read_file_perf_data fname ;
|
||||
read_file_flag := true ) ;
|
||||
if PerfProfilerDataMap.is_empty !global_perf_profiler_data then
|
||||
L.(debug Analysis Medium) "@\n\n[Perf Profiler Log] WARNING: EMPTY PERF PROFILER DATA@\n"
|
||||
|
||||
|
||||
let in_profiler_data_map key =
|
||||
match Config.perf_profiler_data_file with
|
||||
| Some fname ->
|
||||
prepare_perf_data fname ;
|
||||
PerfProfilerDataMap.mem key !global_perf_profiler_data
|
||||
| _ ->
|
||||
false
|
||||
|
||||
|
||||
let get_avg_inclusive_time_opt key =
|
||||
let open IOption.Let_syntax in
|
||||
let* fname = Config.perf_profiler_data_file in
|
||||
prepare_perf_data fname ;
|
||||
let+ {Perf_profiler_t.avg_inclusive_cpu_time_ms} =
|
||||
PerfProfilerDataMap.find_opt key !global_perf_profiler_data
|
||||
in
|
||||
avg_inclusive_cpu_time_ms
|
@ -1,12 +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
|
||||
|
||||
val in_profiler_data_map : Procname.t -> bool
|
||||
|
||||
val get_avg_inclusive_time_opt : Procname.t -> float option
|
@ -1,17 +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.
|
||||
*)
|
||||
|
||||
type perf_profiler_item = {
|
||||
function_name: string;
|
||||
approx_count_trace_id: int;
|
||||
sum_inclusive_cpu_time: float;
|
||||
avg_inclusive_cpu_time_ms: float;
|
||||
sum_exclusive_cpu_time: float;
|
||||
avg_exclusive_cpu_time_ms: float;
|
||||
}
|
||||
|
||||
type perf_profiler = perf_profiler_item list
|
@ -1,35 +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
|
||||
open OUnit2
|
||||
|
||||
let test_parser =
|
||||
let create_test input expected _ =
|
||||
let found = Perf_profiler_j.perf_profiler_of_string input in
|
||||
assert_equal expected found
|
||||
in
|
||||
[ ("test_parser_1", "[]", [])
|
||||
; ( "test_parser_2"
|
||||
, {|[{"function_name":"pkg/cls::\u003Cclinit>",
|
||||
"approx_count_trace_id": 2,
|
||||
"sum_inclusive_cpu_time": 34.4324324,
|
||||
"avg_inclusive_cpu_time_ms":123.01234567899,
|
||||
"sum_exclusive_cpu_time": 17.4543543,
|
||||
"avg_exclusive_cpu_time_ms":9.8765432123456
|
||||
}]|}
|
||||
, [ { Perf_profiler_t.function_name= "pkg/cls::<clinit>"
|
||||
; approx_count_trace_id= 2
|
||||
; sum_inclusive_cpu_time= 34.4324324
|
||||
; avg_inclusive_cpu_time_ms= 123.01234567899
|
||||
; sum_exclusive_cpu_time= 17.4543543
|
||||
; avg_exclusive_cpu_time_ms= 9.8765432123456 } ] ) ]
|
||||
|> List.map ~f:(fun (name, test_input, expected_output) ->
|
||||
name >:: create_test test_input expected_output )
|
||||
|
||||
|
||||
let tests = "java_profiler_samples" >::: test_parser
|
@ -1 +1 @@
|
||||
{"top":{"current":4,"previous":2},"zero":{"current":0,"previous":0},"degrees":[{"degree":0,"current":9,"previous":7},{"degree":100,"current":3,"previous":5},{"degree":101,"current":4,"previous":0},{"degree":200,"current":1,"previous":4}]}
|
||||
{"top":{"current":2,"previous":1},"zero":{"current":0,"previous":0},"degrees":[{"degree":0,"current":6,"previous":5},{"degree":100,"current":2,"previous":3},{"degree":101,"current":2,"previous":0},{"degree":200,"current":1,"previous":2}]}
|
@ -1,65 +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.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
// This class has the following costs:
|
||||
// 1 bottom (zero), 2 constant, 1 linear, 1 top
|
||||
// constructor: constant
|
||||
// f1: top
|
||||
// f2: bottom (zero)
|
||||
// f3: constant
|
||||
// f4: linear
|
||||
// f5: n log n
|
||||
// f6: n log n
|
||||
// f7: top by call to f1
|
||||
|
||||
public class DiffExampleColdStart {
|
||||
|
||||
// cost: top
|
||||
private static void f1(int k) {
|
||||
int i = 0;
|
||||
while (i >=0) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// cost: bottom (0)
|
||||
private static void f2(int k) {}
|
||||
|
||||
// cost: constant (5)
|
||||
private static int f3() {
|
||||
int i, j;
|
||||
i = 17;
|
||||
j = 31;
|
||||
|
||||
return i + j + 3 + 7;
|
||||
}
|
||||
|
||||
// cost: linear
|
||||
private static int f4(int k) {
|
||||
for (int i = 0; i < k; i++) {
|
||||
int [] a = new int[100];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cost: n log n
|
||||
private void f5(ArrayList<Integer> list) {
|
||||
java.util.Collections.sort(list);
|
||||
}
|
||||
|
||||
// cost: n log n
|
||||
private void f6(ArrayList<Integer> list) {
|
||||
f5(list);
|
||||
}
|
||||
|
||||
// cost: top by call to f1
|
||||
private static void f7(int k) {
|
||||
f1(k);
|
||||
}
|
||||
}
|
@ -1,56 +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.
|
||||
*/
|
||||
|
||||
// This class has the following costs:
|
||||
// 2 constant, 1 linear, 1 quadratic
|
||||
// constructor: constant
|
||||
// f1: linear
|
||||
// f2: quadratic
|
||||
// f4: constant
|
||||
// f5: linear
|
||||
// f6: quadratic
|
||||
// f7: top
|
||||
|
||||
public class DiffExampleColdStart {
|
||||
// cost: linear
|
||||
private static int f1(int k) {
|
||||
for (int i = 0; i < k; i++) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// cost: quadratic
|
||||
private static void f2(int k) {
|
||||
for (int i = 0; i < k; i++) {
|
||||
f1(k);
|
||||
}
|
||||
}
|
||||
|
||||
// cost: constant
|
||||
private static int f4(int k) {
|
||||
int i = 1;
|
||||
return i + k;
|
||||
}
|
||||
|
||||
// cost: linear
|
||||
private static void f5(int n) {
|
||||
f1(n);
|
||||
}
|
||||
|
||||
// cost: quadratic
|
||||
private static void f6(int n) {
|
||||
f2(n);
|
||||
}
|
||||
|
||||
// cost: top
|
||||
private static void f7(int k) {
|
||||
int i = 0;
|
||||
while (i >=0) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue