Sin descripción

profile_test.go 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package profile
  15. import (
  16. "bytes"
  17. "fmt"
  18. "io/ioutil"
  19. "path/filepath"
  20. "reflect"
  21. "regexp"
  22. "testing"
  23. "github.com/google/pprof/internal/proftest"
  24. )
  25. func TestParse(t *testing.T) {
  26. const path = "testdata/"
  27. for _, source := range []string{
  28. "go.crc32.cpu",
  29. "go.godoc.thread",
  30. "gobench.cpu",
  31. "gobench.heap",
  32. "cppbench.cpu",
  33. "cppbench.heap",
  34. "cppbench.contention",
  35. "cppbench.growth",
  36. "cppbench.thread",
  37. "cppbench.thread.all",
  38. "cppbench.thread.none",
  39. "java.cpu",
  40. "java.heap",
  41. "java.contention",
  42. } {
  43. inbytes, err := ioutil.ReadFile(filepath.Join(path, source))
  44. if err != nil {
  45. t.Fatal(err)
  46. }
  47. p, err := Parse(bytes.NewBuffer(inbytes))
  48. if err != nil {
  49. t.Fatalf("%s: %s", source, err)
  50. }
  51. js := p.String()
  52. goldFilename := path + source + ".string"
  53. gold, err := ioutil.ReadFile(goldFilename)
  54. if err != nil {
  55. t.Fatalf("%s: %v", source, err)
  56. }
  57. if js != string(gold) {
  58. t.Errorf("diff %s %s", source, goldFilename)
  59. d, err := proftest.Diff(gold, []byte(js))
  60. if err != nil {
  61. t.Fatalf("%s: %v", source, err)
  62. }
  63. t.Error(source + "\n" + string(d) + "\n" + "new profile at:\n" + leaveTempfile([]byte(js)))
  64. }
  65. // Reencode and decode.
  66. bw := bytes.NewBuffer(nil)
  67. if err := p.Write(bw); err != nil {
  68. t.Fatalf("%s: %v", source, err)
  69. }
  70. if p, err = Parse(bw); err != nil {
  71. t.Fatalf("%s: %v", source, err)
  72. }
  73. js2 := p.String()
  74. if js2 != string(gold) {
  75. d, err := proftest.Diff(gold, []byte(js2))
  76. if err != nil {
  77. t.Fatalf("%s: %v", source, err)
  78. }
  79. t.Error(source + "\n" + string(d) + "\n" + "gold:\n" + goldFilename +
  80. "\nnew profile at:\n" + leaveTempfile([]byte(js)))
  81. }
  82. }
  83. }
  84. // leaveTempfile leaves |b| in a temporary file on disk and returns the
  85. // temp filename. This is useful to recover a profile when the test
  86. // fails.
  87. func leaveTempfile(b []byte) string {
  88. f1, err := ioutil.TempFile("", "profile_test")
  89. if err != nil {
  90. panic(err)
  91. }
  92. if _, err := f1.Write(b); err != nil {
  93. panic(err)
  94. }
  95. return f1.Name()
  96. }
  97. const mainBinary = "/bin/main"
  98. var cpuM = []*Mapping{
  99. {
  100. ID: 1,
  101. Start: 0x10000,
  102. Limit: 0x40000,
  103. File: mainBinary,
  104. HasFunctions: true,
  105. HasFilenames: true,
  106. HasLineNumbers: true,
  107. HasInlineFrames: true,
  108. },
  109. {
  110. ID: 2,
  111. Start: 0x1000,
  112. Limit: 0x4000,
  113. File: "/lib/lib.so",
  114. HasFunctions: true,
  115. HasFilenames: true,
  116. HasLineNumbers: true,
  117. HasInlineFrames: true,
  118. },
  119. {
  120. ID: 3,
  121. Start: 0x4000,
  122. Limit: 0x5000,
  123. File: "/lib/lib2_c.so.6",
  124. HasFunctions: true,
  125. HasFilenames: true,
  126. HasLineNumbers: true,
  127. HasInlineFrames: true,
  128. },
  129. {
  130. ID: 4,
  131. Start: 0x5000,
  132. Limit: 0x9000,
  133. File: "/lib/lib.so_6 (deleted)",
  134. HasFunctions: true,
  135. HasFilenames: true,
  136. HasLineNumbers: true,
  137. HasInlineFrames: true,
  138. },
  139. }
  140. var cpuF = []*Function{
  141. {ID: 1, Name: "main", SystemName: "main", Filename: "main.c"},
  142. {ID: 2, Name: "foo", SystemName: "foo", Filename: "foo.c"},
  143. {ID: 3, Name: "foo_caller", SystemName: "foo_caller", Filename: "foo.c"},
  144. }
  145. var cpuL = []*Location{
  146. {
  147. ID: 1000,
  148. Mapping: cpuM[1],
  149. Address: 0x1000,
  150. Line: []Line{
  151. {Function: cpuF[0], Line: 1},
  152. },
  153. },
  154. {
  155. ID: 2000,
  156. Mapping: cpuM[0],
  157. Address: 0x2000,
  158. Line: []Line{
  159. {Function: cpuF[1], Line: 2},
  160. {Function: cpuF[2], Line: 1},
  161. },
  162. },
  163. {
  164. ID: 3000,
  165. Mapping: cpuM[0],
  166. Address: 0x3000,
  167. Line: []Line{
  168. {Function: cpuF[1], Line: 2},
  169. {Function: cpuF[2], Line: 1},
  170. },
  171. },
  172. {
  173. ID: 3001,
  174. Mapping: cpuM[0],
  175. Address: 0x3001,
  176. Line: []Line{
  177. {Function: cpuF[2], Line: 2},
  178. },
  179. },
  180. {
  181. ID: 3002,
  182. Mapping: cpuM[0],
  183. Address: 0x3002,
  184. Line: []Line{
  185. {Function: cpuF[2], Line: 3},
  186. },
  187. },
  188. }
  189. var testProfile = &Profile{
  190. PeriodType: &ValueType{Type: "cpu", Unit: "milliseconds"},
  191. Period: 1,
  192. DurationNanos: 10e9,
  193. SampleType: []*ValueType{
  194. {Type: "samples", Unit: "count"},
  195. {Type: "cpu", Unit: "milliseconds"},
  196. },
  197. Sample: []*Sample{
  198. {
  199. Location: []*Location{cpuL[0]},
  200. Value: []int64{1000, 1000},
  201. Label: map[string][]string{
  202. "key1": []string{"tag1"},
  203. "key2": []string{"tag1"},
  204. },
  205. },
  206. {
  207. Location: []*Location{cpuL[1], cpuL[0]},
  208. Value: []int64{100, 100},
  209. Label: map[string][]string{
  210. "key1": []string{"tag2"},
  211. "key3": []string{"tag2"},
  212. },
  213. },
  214. {
  215. Location: []*Location{cpuL[2], cpuL[0]},
  216. Value: []int64{10, 10},
  217. Label: map[string][]string{
  218. "key1": []string{"tag3"},
  219. "key2": []string{"tag2"},
  220. },
  221. },
  222. {
  223. Location: []*Location{cpuL[3], cpuL[0]},
  224. Value: []int64{10000, 10000},
  225. Label: map[string][]string{
  226. "key1": []string{"tag4"},
  227. "key2": []string{"tag1"},
  228. },
  229. },
  230. {
  231. Location: []*Location{cpuL[4], cpuL[0]},
  232. Value: []int64{1, 1},
  233. Label: map[string][]string{
  234. "key1": []string{"tag4"},
  235. "key2": []string{"tag1"},
  236. },
  237. },
  238. },
  239. Location: cpuL,
  240. Function: cpuF,
  241. Mapping: cpuM,
  242. }
  243. var aggTests = map[string]aggTest{
  244. "precise": aggTest{true, true, true, true, 5},
  245. "fileline": aggTest{false, true, true, true, 4},
  246. "inline_function": aggTest{false, true, false, true, 3},
  247. "function": aggTest{false, true, false, false, 2},
  248. }
  249. type aggTest struct {
  250. precise, function, fileline, inlineFrame bool
  251. rows int
  252. }
  253. const totalSamples = int64(11111)
  254. func TestAggregation(t *testing.T) {
  255. prof := testProfile.Copy()
  256. for _, resolution := range []string{"precise", "fileline", "inline_function", "function"} {
  257. a := aggTests[resolution]
  258. if !a.precise {
  259. if err := prof.Aggregate(a.inlineFrame, a.function, a.fileline, a.fileline, false); err != nil {
  260. t.Error("aggregating to " + resolution + ":" + err.Error())
  261. }
  262. }
  263. if err := checkAggregation(prof, &a); err != nil {
  264. t.Error("failed aggregation to " + resolution + ": " + err.Error())
  265. }
  266. }
  267. }
  268. // checkAggregation verifies that the profile remained consistent
  269. // with its aggregation.
  270. func checkAggregation(prof *Profile, a *aggTest) error {
  271. // Check that the total number of samples for the rows was preserved.
  272. total := int64(0)
  273. samples := make(map[string]bool)
  274. for _, sample := range prof.Sample {
  275. tb := locationHash(sample)
  276. samples[tb] = true
  277. total += sample.Value[0]
  278. }
  279. if total != totalSamples {
  280. return fmt.Errorf("sample total %d, want %d", total, totalSamples)
  281. }
  282. // Check the number of unique sample locations
  283. if a.rows != len(samples) {
  284. return fmt.Errorf("number of samples %d, want %d", len(samples), a.rows)
  285. }
  286. // Check that all mappings have the right detail flags.
  287. for _, m := range prof.Mapping {
  288. if m.HasFunctions != a.function {
  289. return fmt.Errorf("unexpected mapping.HasFunctions %v, want %v", m.HasFunctions, a.function)
  290. }
  291. if m.HasFilenames != a.fileline {
  292. return fmt.Errorf("unexpected mapping.HasFilenames %v, want %v", m.HasFilenames, a.fileline)
  293. }
  294. if m.HasLineNumbers != a.fileline {
  295. return fmt.Errorf("unexpected mapping.HasLineNumbers %v, want %v", m.HasLineNumbers, a.fileline)
  296. }
  297. if m.HasInlineFrames != a.inlineFrame {
  298. return fmt.Errorf("unexpected mapping.HasInlineFrames %v, want %v", m.HasInlineFrames, a.inlineFrame)
  299. }
  300. }
  301. // Check that aggregation has removed finer resolution data.
  302. for _, l := range prof.Location {
  303. if !a.inlineFrame && len(l.Line) > 1 {
  304. return fmt.Errorf("found %d lines on location %d, want 1", len(l.Line), l.ID)
  305. }
  306. for _, ln := range l.Line {
  307. if !a.fileline && (ln.Function.Filename != "" || ln.Line != 0) {
  308. return fmt.Errorf("found line %s:%d on location %d, want :0",
  309. ln.Function.Filename, ln.Line, l.ID)
  310. }
  311. if !a.function && (ln.Function.Name != "") {
  312. return fmt.Errorf(`found file %s location %d, want ""`,
  313. ln.Function.Name, l.ID)
  314. }
  315. }
  316. }
  317. return nil
  318. }
  319. func TestParseMappingEntry(t *testing.T) {
  320. for _, test := range []*struct {
  321. entry string
  322. want *Mapping
  323. }{
  324. {
  325. entry: "00400000-02e00000 r-xp 00000000 00:00 0",
  326. want: &Mapping{
  327. Start: 0x400000,
  328. Limit: 0x2e00000,
  329. },
  330. },
  331. {
  332. entry: "02e00000-02e8a000 r-xp 02a00000 00:00 15953927 /foo/bin",
  333. want: &Mapping{
  334. Start: 0x2e00000,
  335. Limit: 0x2e8a000,
  336. Offset: 0x2a00000,
  337. File: "/foo/bin",
  338. },
  339. },
  340. {
  341. entry: "02e00000-02e8a000 r-xp 000000 00:00 15953927 [vdso]",
  342. want: &Mapping{
  343. Start: 0x2e00000,
  344. Limit: 0x2e8a000,
  345. File: "[vdso]",
  346. },
  347. },
  348. {
  349. entry: " 02e00000-02e8a000: /foo/bin (@2a00000)",
  350. want: &Mapping{
  351. Start: 0x2e00000,
  352. Limit: 0x2e8a000,
  353. Offset: 0x2a00000,
  354. File: "/foo/bin",
  355. },
  356. },
  357. {
  358. entry: " 02e00000-02e8a000: /foo/bin",
  359. want: &Mapping{
  360. Start: 0x2e00000,
  361. Limit: 0x2e8a000,
  362. File: "/foo/bin",
  363. },
  364. },
  365. {
  366. entry: " 02e00000-02e8a000: [vdso]",
  367. want: &Mapping{
  368. Start: 0x2e00000,
  369. Limit: 0x2e8a000,
  370. File: "[vdso]",
  371. },
  372. },
  373. } {
  374. got, err := parseMappingEntry(test.entry)
  375. if err != nil {
  376. t.Error(err)
  377. }
  378. if !reflect.DeepEqual(test.want, got) {
  379. t.Errorf("%s want=%v got=%v", test.entry, test.want, got)
  380. }
  381. }
  382. }
  383. // Test merge leaves the main binary in place.
  384. func TestMergeMain(t *testing.T) {
  385. prof := testProfile.Copy()
  386. p1, err := Merge([]*Profile{prof})
  387. if err != nil {
  388. t.Fatalf("merge error: %v", err)
  389. }
  390. if cpuM[0].File != p1.Mapping[0].File {
  391. t.Errorf("want Mapping[0]=%s got %s", cpuM[0].File, p1.Mapping[0].File)
  392. }
  393. }
  394. func TestMerge(t *testing.T) {
  395. // Aggregate a profile with itself and once again with a factor of
  396. // -2. Should end up with an empty profile (all samples for a
  397. // location should add up to 0).
  398. prof := testProfile.Copy()
  399. p1, err := Merge([]*Profile{prof, prof})
  400. if err != nil {
  401. t.Errorf("merge error: %v", err)
  402. }
  403. prof.Scale(-2)
  404. prof, err = Merge([]*Profile{p1, prof})
  405. if err != nil {
  406. t.Errorf("merge error: %v", err)
  407. }
  408. // Use aggregation to merge locations at function granularity.
  409. if err := prof.Aggregate(false, true, false, false, false); err != nil {
  410. t.Errorf("aggregating after merge: %v", err)
  411. }
  412. samples := make(map[string]int64)
  413. for _, s := range prof.Sample {
  414. tb := locationHash(s)
  415. samples[tb] = samples[tb] + s.Value[0]
  416. }
  417. for s, v := range samples {
  418. if v != 0 {
  419. t.Errorf("nonzero value for sample %s: %d", s, v)
  420. }
  421. }
  422. }
  423. func TestMergeAll(t *testing.T) {
  424. // Aggregate 10 copies of the profile.
  425. profs := make([]*Profile, 10)
  426. for i := 0; i < 10; i++ {
  427. profs[i] = testProfile.Copy()
  428. }
  429. prof, err := Merge(profs)
  430. if err != nil {
  431. t.Errorf("merge error: %v", err)
  432. }
  433. samples := make(map[string]int64)
  434. for _, s := range prof.Sample {
  435. tb := locationHash(s)
  436. samples[tb] = samples[tb] + s.Value[0]
  437. }
  438. for _, s := range testProfile.Sample {
  439. tb := locationHash(s)
  440. if samples[tb] != s.Value[0]*10 {
  441. t.Errorf("merge got wrong value at %s : %d instead of %d", tb, samples[tb], s.Value[0]*10)
  442. }
  443. }
  444. }
  445. func TestFilter(t *testing.T) {
  446. // Perform several forms of filtering on the test profile.
  447. type filterTestcase struct {
  448. focus, ignore, hide, show *regexp.Regexp
  449. fm, im, hm, hnm bool
  450. }
  451. for tx, tc := range []filterTestcase{
  452. {nil, nil, nil, nil, true, false, false, false},
  453. {regexp.MustCompile("notfound"), nil, nil, nil, false, false, false, false},
  454. {nil, regexp.MustCompile("foo.c"), nil, nil, true, true, false, false},
  455. {nil, nil, regexp.MustCompile("lib.so"), nil, true, false, true, false},
  456. } {
  457. prof := *testProfile.Copy()
  458. gf, gi, gh, gnh := prof.FilterSamplesByName(tc.focus, tc.ignore, tc.hide, tc.show)
  459. if gf != tc.fm {
  460. t.Errorf("Filter #%d, got fm=%v, want %v", tx, gf, tc.fm)
  461. }
  462. if gi != tc.im {
  463. t.Errorf("Filter #%d, got im=%v, want %v", tx, gi, tc.im)
  464. }
  465. if gh != tc.hm {
  466. t.Errorf("Filter #%d, got hm=%v, want %v", tx, gh, tc.hm)
  467. }
  468. if gnh != tc.hnm {
  469. t.Errorf("Filter #%d, got hnm=%v, want %v", tx, gnh, tc.hnm)
  470. }
  471. }
  472. }
  473. // locationHash constructs a string to use as a hashkey for a sample, based on its locations
  474. func locationHash(s *Sample) string {
  475. var tb string
  476. for _, l := range s.Location {
  477. for _, ln := range l.Line {
  478. tb = tb + fmt.Sprintf("%s:%d@%d ", ln.Function.Name, ln.Line, l.Address)
  479. }
  480. }
  481. return tb
  482. }
  483. func TestSetMain(t *testing.T) {
  484. testProfile.massageMappings()
  485. if testProfile.Mapping[0].File != mainBinary {
  486. t.Errorf("got %s for main", testProfile.Mapping[0].File)
  487. }
  488. }
  489. // Benchmarks
  490. // benchmarkMerge measures the overhead of merging profiles read from files.
  491. // They must be the same type of profiles.
  492. func benchmarkMerge(b *testing.B, files []string) {
  493. const path = "testdata/"
  494. p := make([]*Profile, len(files))
  495. for i, source := range files {
  496. inBytes, err := ioutil.ReadFile(filepath.Join(path, source))
  497. if err != nil {
  498. b.Fatal(err)
  499. }
  500. if p[i], err = Parse(bytes.NewBuffer(inBytes)); err != nil {
  501. b.Fatalf("%s: %s", source, err)
  502. }
  503. }
  504. var prof *Profile
  505. b.ResetTimer()
  506. for i := 0; i < b.N; i++ {
  507. prof, _ = Merge(p)
  508. }
  509. b.StopTimer()
  510. before := 0
  511. for _, p := range p {
  512. p.preEncode()
  513. buff := marshal(p)
  514. before += len(buff)
  515. }
  516. prof.preEncode()
  517. buff := marshal(prof)
  518. after := len(buff)
  519. b.Logf("Profile size before merge = %v, After merge = %v", before, after)
  520. }
  521. // BenchmarkMergeCppCPUMedium measures the overhead of merging two medium CPU
  522. // profiles of a C++ program (muppet).
  523. func BenchmarkMergeCppCPUMedium(b *testing.B) {
  524. files := []string{
  525. "muppet.profilez.medium.1.pb.gz",
  526. "muppet.profilez.medium.2.pb.gz",
  527. }
  528. benchmarkMerge(b, files)
  529. }
  530. // BenchmarkMergeCppHeapMedium measures the overhead of merging two medium Heap
  531. // profiles of a C++ program (muppet).
  532. func BenchmarkMergeCppHeapMedium(b *testing.B) {
  533. files := []string{
  534. "muppet.heapz.medium.1.pb.gz",
  535. "muppet.heapz.medium.2.pb.gz",
  536. }
  537. benchmarkMerge(b, files)
  538. }
  539. // BenchmarkMergeCppContentionMedium measures the overhead of merging two medium
  540. // contention profiles of a C++ program (muppet).
  541. func BenchmarkMergeCppContentionMedium(b *testing.B) {
  542. files := []string{
  543. "muppet.contentionz.medium.1.pb.gz",
  544. "muppet.contentionz.medium.2.pb.gz",
  545. }
  546. benchmarkMerge(b, files)
  547. }
  548. // BenchmarkMergeJavaCPUMedium measures the overhead of merging two medium CPU
  549. // profiles of a Java program (caribou).
  550. func BenchmarkMergeJavaCPUMedium(b *testing.B) {
  551. files := []string{
  552. "caribou.profilez.medium.1.pb.gz",
  553. "caribou.profilez.medium.2.pb.gz",
  554. }
  555. benchmarkMerge(b, files)
  556. }
  557. // BenchmarkMergeJavaHeapMedium measures the overhead of merging two medium Heap
  558. // profiles of a Java program (caribou).
  559. func BenchmarkMergeJavaHeapMedium(b *testing.B) {
  560. files := []string{
  561. "caribou.heapz.medium.1.pb.gz",
  562. "caribou.heapz.medium.2.pb.gz",
  563. }
  564. benchmarkMerge(b, files)
  565. }
  566. // BenchmarkMergeJavaContentionMedium measures the overhead of merging two medium
  567. // contention profiles of a Java program (caribou).
  568. func BenchmarkMergeJavaContentionMedium(b *testing.B) {
  569. files := []string{
  570. "caribou.contentionz.medium.1.pb.gz",
  571. "caribou.contentionz.medium.2.pb.gz",
  572. }
  573. benchmarkMerge(b, files)
  574. }
  575. // BenchmarkMergeCppCPULarge measures the overhead of merging two large CPU
  576. // profiles of a C++ program (muppet).
  577. func BenchmarkMergeCppCPULarge(b *testing.B) {
  578. files := []string{
  579. "muppet.profilez.large.1.pb.gz",
  580. "muppet.profilez.large.2.pb.gz",
  581. }
  582. benchmarkMerge(b, files)
  583. }
  584. // BenchmarkMergeCppHeapLarge measures the overhead of merging two large Heap
  585. // profiles of a C++ program (muppet).
  586. func BenchmarkMergeCppHeapLarge(b *testing.B) {
  587. files := []string{
  588. "muppet.heapz.large.1.pb.gz",
  589. "muppet.heapz.large.2.pb.gz",
  590. }
  591. benchmarkMerge(b, files)
  592. }
  593. // BenchmarkMergeCppContentionLarge measures the overhead of merging two large
  594. // contention profiles of a C++ program (muppet).
  595. func BenchmarkMergeCppContentionLarge(b *testing.B) {
  596. files := []string{
  597. "muppet.contentionz.large.1.pb.gz",
  598. "muppet.contentionz.large.2.pb.gz",
  599. }
  600. benchmarkMerge(b, files)
  601. }
  602. // BenchmarkMergeJavaCPULarge measures the overhead of merging two large CPU
  603. // profiles of a Java program (caribou).
  604. func BenchmarkMergeJavaCPULarge(b *testing.B) {
  605. files := []string{
  606. "caribou.profilez.large.1.pb.gz",
  607. "caribou.profilez.large.2.pb.gz",
  608. }
  609. benchmarkMerge(b, files)
  610. }
  611. // BenchmarkMergeJavaHeapLarge measures the overhead of merging two large Heap
  612. // profiles of a Java program (caribou).
  613. func BenchmarkMergeJavaHeapLarge(b *testing.B) {
  614. files := []string{
  615. "caribou.heapz.large.1.pb.gz",
  616. "caribou.heapz.large.2.pb.gz",
  617. }
  618. benchmarkMerge(b, files)
  619. }
  620. // BenchmarkMergeJavaContentionLarge measures the overhead of merging two large
  621. // contention profiles of a Java program (caribou).
  622. func BenchmarkMergeJavaContentionLarge(b *testing.B) {
  623. files := []string{
  624. "caribou.contentionz.large.1.pb.gz",
  625. "caribou.contentionz.large.2.pb.gz",
  626. }
  627. benchmarkMerge(b, files)
  628. }
  629. // BenchmarkMergeJavaCPUWorst measures the overhead of merging rollups worth 7 days
  630. // for the worst case scenario. These rollups are generated by merging samples
  631. // (10 seconds/min) from /profilez handler of caribou prod jobs. They are deduplicated
  632. // so that Samples, Locations, Mappings, and Functions are unique.
  633. func BenchmarkMergeJavaCPUWorst(b *testing.B) {
  634. files := []string{
  635. "caribou.profilez.1min.1.pb.gz",
  636. "caribou.profilez.1min.2.pb.gz",
  637. "caribou.profilez.1min.3.pb.gz",
  638. "caribou.profilez.1min.4.pb.gz",
  639. "caribou.profilez.1min.5.pb.gz",
  640. "caribou.profilez.1min.6.pb.gz",
  641. "caribou.profilez.1min.7.pb.gz",
  642. "caribou.profilez.1min.8.pb.gz",
  643. "caribou.profilez.1min.9.pb.gz",
  644. "caribou.profilez.1min.10.pb.gz",
  645. "caribou.profilez.1min.11.pb.gz",
  646. "caribou.profilez.1min.12.pb.gz",
  647. "caribou.profilez.1min.13.pb.gz",
  648. "caribou.profilez.1min.14.pb.gz",
  649. "caribou.profilez.1min.15.pb.gz",
  650. "caribou.profilez.1min.16.pb.gz",
  651. "caribou.profilez.1min.17.pb.gz",
  652. "caribou.profilez.1min.18.pb.gz",
  653. "caribou.profilez.10mins.1.pb.gz",
  654. "caribou.profilez.10mins.2.pb.gz",
  655. "caribou.profilez.10mins.3.pb.gz",
  656. "caribou.profilez.10mins.4.pb.gz",
  657. "caribou.profilez.10mins.5.pb.gz",
  658. "caribou.profilez.10mins.6.pb.gz",
  659. "caribou.profilez.10mins.7.pb.gz",
  660. "caribou.profilez.10mins.8.pb.gz",
  661. "caribou.profilez.10mins.9.pb.gz",
  662. "caribou.profilez.10mins.10.pb.gz",
  663. "caribou.profilez.1hour.1.pb.gz",
  664. "caribou.profilez.1hour.2.pb.gz",
  665. "caribou.profilez.1hour.3.pb.gz",
  666. "caribou.profilez.1hour.4.pb.gz",
  667. "caribou.profilez.1hour.5.pb.gz",
  668. "caribou.profilez.1hour.6.pb.gz",
  669. "caribou.profilez.4hours.1.pb.gz",
  670. "caribou.profilez.4hours.2.pb.gz",
  671. "caribou.profilez.4hours.3.pb.gz",
  672. "caribou.profilez.4hours.4.pb.gz",
  673. "caribou.profilez.12hours.1.pb.gz",
  674. "caribou.profilez.12hours.2.pb.gz",
  675. "caribou.profilez.1day.1.pb.gz",
  676. "caribou.profilez.1day.2.pb.gz",
  677. "caribou.profilez.1day.3.pb.gz",
  678. "caribou.profilez.1day.4.pb.gz",
  679. "caribou.profilez.1day.5.pb.gz",
  680. }
  681. benchmarkMerge(b, files)
  682. }