|
894 | 894 |
|
895 | 895 | cpu_and_wall_time_worker.stop
|
896 | 896 |
|
| 897 | + current_method_name = caller_locations(0, 1).first.base_label |
| 898 | + |
897 | 899 | test_struct_heap_sample = lambda { |sample|
|
898 | 900 | first_frame = sample.locations.first
|
899 | 901 | first_frame.lineno == allocation_line &&
|
900 | 902 | first_frame.path == __FILE__ &&
|
901 |
| - first_frame.base_label == "new" && |
| 903 | + ( |
| 904 | + first_frame.base_label == "new" || |
| 905 | + # From Ruby 3.5 onwards, new is inlined into the bytecode of the caller and there's no "new" |
| 906 | + # frame, see https://github.com/ruby/ruby/pull/13080 |
| 907 | + (RUBY_VERSION >= "3.5.0" && first_frame.base_label == current_method_name) |
| 908 | + ) && |
902 | 909 | sample.labels[:"allocation class"] == "CpuAndWallTimeWorkerSpec::TestStruct" &&
|
903 | 910 | (sample.values[:"heap-live-samples"] || 0) > 0
|
904 | 911 | }
|
905 | 912 |
|
906 | 913 | # We can't just use find here because samples might have different gc age labels
|
907 | 914 | # if a gc happens to run in the middle of this test. Thus, we'll have to sum up
|
908 | 915 | # together the values of all matching samples.
|
909 |
| - relevant_samples = samples_from_pprof(recorder.serialize!) |
910 |
| - .select(&test_struct_heap_sample) |
| 916 | + relevant_samples = samples_from_pprof(recorder.serialize!).select(&test_struct_heap_sample) |
911 | 917 |
|
912 | 918 | total_samples = relevant_samples.map { |sample| sample.values[:"heap-live-samples"] || 0 }.reduce(:+)
|
913 | 919 | total_size = relevant_samples.map { |sample| sample.values[:"heap-live-size"] || 0 }.reduce(:+)
|
914 | 920 |
|
915 | 921 | expect(total_samples).to eq test_num_allocated_object
|
916 |
| - # 40 is the size of a basic object and we have test_num_allocated_object of them |
917 |
| - expect(total_size).to eq test_num_allocated_object * 40 |
| 922 | + |
| 923 | + expected_size_of_object = 40 # 40 is the size of a basic object and we have test_num_allocated_object of them |
| 924 | + |
| 925 | + # Starting with Ruby 3.5, the object_id counts towards the object's size |
| 926 | + if RUBY_VERSION >= "3.5.0" |
| 927 | + expected_size_of_object = 104 |
| 928 | + |
| 929 | + expect(ObjectSpace.memsize_of(CpuAndWallTimeWorkerSpec::TestStruct.new.tap(&:object_id))) |
| 930 | + .to be expected_size_of_object |
| 931 | + end |
| 932 | + |
| 933 | + expect(total_size).to eq test_num_allocated_object * expected_size_of_object |
918 | 934 | end
|
919 | 935 |
|
920 | 936 | describe "heap cleanup after GC" do
|
|
0 commit comments