[codesize] Add support to parse Bloaty files for Android

Bug: skia:13657
Change-Id: I504f5a6617839d70cb01c5ac72dd1ee37c25d6e0
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/585407
Commit-Queue: Kevin Lubick <kjlubick@google.com>
Reviewed-by: Leandro Lovisolo <lovisolo@google.com>
diff --git a/codesize/go/bloaty/bloaty.go b/codesize/go/bloaty/bloaty.go
index 8db8c6d..aece0a7 100644
--- a/codesize/go/bloaty/bloaty.go
+++ b/codesize/go/bloaty/bloaty.go
@@ -47,9 +47,13 @@
 	FileSize int
 }
 
-// expectedHeaderLine is the header line we expect to find in a Bloaty output file. We use this to
-// ensure that Bloaty was invoked with the expected command-line flags.
-const expectedHeaderLine = "compileunits\tsymbols\tvmsize\tfilesize"
+const (
+	// expectedHeaderLine is the header line we expect to find in a Bloaty output file. We use
+	// this to ensure that Bloaty was invoked with the expected command-line flags.
+	expectedHeaderLine = "compileunits\tsymbols\tvmsize\tfilesize"
+
+	androidBuildPrefix = "/buildbot/src/android/"
+)
 
 // ParseTSVOutput parses the TSV output of Bloaty.
 //
@@ -63,7 +67,7 @@
 
 	var items []OutputItem
 
-	for i, line := range strings.Split(strings.TrimSpace(string(bloatyOutput)), "\n") {
+	for i, line := range strings.Split(strings.TrimSpace(bloatyOutput), "\n") {
 		errOnLine := func(msg string, args ...interface{}) error {
 			allArgs := append([]interface{}{i + 1}, args...)
 			return skerr.Fmt("on line %d: "+msg, allArgs...)
@@ -110,6 +114,11 @@
 			// to have duplicate symbols which makes the treemap sad.
 			item.Symbol += " " + item.CompileUnit
 		}
+		// In arm outputs, we see sections show up, which causes cycles in the treemap.
+		// Thus, we skip them. They seem pretty small too.
+		if strings.HasPrefix(item.Symbol, "[section") {
+			continue
+		}
 
 		var err error
 		item.VirtualMemorySize, err = strconv.Atoi(cols[2])
@@ -132,10 +141,13 @@
 			item.CompileUnit = strings.TrimPrefix(item.CompileUnit, "skia/")
 		}
 
-		// Files in third_party sometimes have absolute paths. Strip those.
+		// Files in third_party and from the NDK sometimes have absolute paths. Strip those.
 		if path.IsAbs(item.CompileUnit) {
+			item.CompileUnit = path.Clean(item.CompileUnit)
 			if idx := strings.Index(item.CompileUnit, "third_party"); idx != -1 {
 				item.CompileUnit = item.CompileUnit[idx:]
+			} else if strings.HasPrefix(item.CompileUnit, androidBuildPrefix) {
+				item.CompileUnit = strings.TrimPrefix(item.CompileUnit, androidBuildPrefix)
 			} else {
 				return nil, errOnLine("unexpected absolute path %q", line)
 			}
diff --git a/codesize/go/bloaty/bloaty_test.go b/codesize/go/bloaty/bloaty_test.go
index 7ea70ff..e886d33 100644
--- a/codesize/go/bloaty/bloaty_test.go
+++ b/codesize/go/bloaty/bloaty_test.go
@@ -47,6 +47,7 @@
 ../../dm/DMSrcSink.cpp	DM::CodecSrc::draw()	7307	7382
 ../../src/sksl/SkSLCompiler.cpp	(anonymous namespace)::TLSCurrentObjects::Get()::objects	0	16
 ../../../../../../skia/third_party/externals/libwebp/src/enc/vp8l_enc.c	EncodeStreamHook	7656	7656
+/mnt/pd0/s/w/ir/skia/third_party/externals/zlib/cpu_features.c	Cr_z_cpu_check_features	1567	2994
 [section .rodata]	[section .rodata]	10425940	10425940
 [section .rodata]	propsVectorsTrie_index	62456	62456
 [section .text]	png_create_read_struct_2	75	75
@@ -67,12 +68,6 @@
 			FileSize:          13,
 		},
 		{
-			CompileUnit:       "third_party/externals/harfbuzz/src/hb-subset.cc",
-			Symbol:            "[section .debug_info]",
-			VirtualMemorySize: 0,
-			FileSize:          4213071,
-		},
-		{
 			CompileUnit:       "dm/DMSrcSink.cpp",
 			Symbol:            "(anonymous namespace)::TLSCurrentObjects::Get()::objects",
 			VirtualMemorySize: 0,
@@ -97,6 +92,12 @@
 			FileSize:          7656,
 		},
 		{
+			CompileUnit:       "third_party/externals/zlib/cpu_features.c",
+			Symbol:            "Cr_z_cpu_check_features",
+			VirtualMemorySize: 1567,
+			FileSize:          2994,
+		},
+		{
 			CompileUnit:       "[section .rodata]",
 			Symbol:            "UNKNOWN [section .rodata]",
 			VirtualMemorySize: 10425940,
@@ -130,6 +131,57 @@
 		items)
 }
 
+func TestParseTSVOutput_HandlesAndroidNDKFiles(t *testing.T) {
+	// If a symbol is a "section", it should be omitted. We should also clean up the file paths
+
+	const testData = `compileunits	symbols	vmsize	filesize
+/buildbot/src/android/ndk-release-r21/external/libcxx/src/locale.cpp	std::__ndk1::num_put<>::do_put()	6504	6504
+/buildbot/src/android/ndk-release-r21/external/libcxx/../../external/libunwind_llvm/src/UnwindRegistersSave.S	[section .text]	48	48
+/buildbot/src/android/ndk-release-r21/external/libcxx/../../external/libunwind_llvm/src/UnwindRegistersSave.S	[section .dynsym]	16	16
+/buildbot/src/android/ndk-release-r21/external/libcxx/../../external/libunwind_llvm/src/UnwindRegistersSave.S	[section .dynstr]	15	15
+/mnt/pd0/s/w/ir/skia/third_party/externals/dng_sdk/source/dng_abort_sniffer.cpp	_GLOBAL__sub_I_dng_abort_sniffer.cpp	43	43
+/mnt/pd0/s/w/ir/skia/third_party/externals/dng_sdk/source/dng_abort_sniffer.cpp	dng_abort_sniffer::SniffForAbort()	35	35
+/mnt/pd0/s/w/ir/skia/third_party/externals/dng_sdk/source/dng_abort_sniffer.cpp	[section .text]	1	1
+/mnt/pd0/s/w/ir/skia/third_party/externals/harfbuzz/src/hb-ot-layout.cc	OT::HeadlessArrayOf<>::operator[]()	84	84
+../../../../../../skia/src/sksl/ir/SkSLType.cpp	std::__ndk1::unique_ptr<>::~unique_ptr()	9	9
+`
+
+	rv, err := ParseTSVOutput(testData)
+	require.NoError(t, err)
+	assert.Equal(t, []OutputItem{
+		{
+			CompileUnit:       "ndk-release-r21/external/libcxx/src/locale.cpp",
+			Symbol:            "std::__ndk1::num_put<>::do_put()",
+			VirtualMemorySize: 6504,
+			FileSize:          6504,
+		},
+		{
+			CompileUnit:       "third_party/externals/dng_sdk/source/dng_abort_sniffer.cpp",
+			Symbol:            "_GLOBAL__sub_I_dng_abort_sniffer.cpp",
+			VirtualMemorySize: 43,
+			FileSize:          43,
+		},
+		{
+			CompileUnit:       "third_party/externals/dng_sdk/source/dng_abort_sniffer.cpp",
+			Symbol:            "dng_abort_sniffer::SniffForAbort()",
+			VirtualMemorySize: 35,
+			FileSize:          35,
+		},
+		{
+			CompileUnit:       "third_party/externals/harfbuzz/src/hb-ot-layout.cc",
+			Symbol:            "OT::HeadlessArrayOf<>::operator[]()",
+			VirtualMemorySize: 84,
+			FileSize:          84,
+		},
+		{
+			CompileUnit:       "skia/src/sksl/ir/SkSLType.cpp",
+			Symbol:            "std::__ndk1::unique_ptr<>::~unique_ptr()",
+			VirtualMemorySize: 9,
+			FileSize:          9,
+		},
+	}, rv)
+}
+
 func TestGenTreeMapDataTable_AllRowsCreatedInSpecifiedOrder(t *testing.T) {
 
 	items, err := ParseTSVOutput(sampleBloatyOutput)
@@ -259,16 +311,6 @@
 			Size:   13,
 		},
 		{
-			Name:   "third_party/externals/harfbuzz/src/hb-subset.cc",
-			Parent: "third_party/externals/harfbuzz/src",
-			Size:   0,
-		},
-		{
-			Name:   "[section .debug_info]",
-			Parent: "third_party/externals/harfbuzz/src/hb-subset.cc",
-			Size:   4213071,
-		},
-		{
 			Name:   "third_party/externals/libwebp",
 			Parent: "third_party/externals",
 			Size:   0,
@@ -293,6 +335,21 @@
 			Parent: "third_party/externals/libwebp/src/enc/vp8l_enc.c",
 			Size:   7656,
 		},
+		{
+			Name:   "third_party/externals/zlib",
+			Parent: "third_party/externals",
+			Size:   0,
+		},
+		{
+			Name:   "third_party/externals/zlib/cpu_features.c",
+			Parent: "third_party/externals/zlib",
+			Size:   0,
+		},
+		{
+			Name:   "Cr_z_cpu_check_features",
+			Parent: "third_party/externals/zlib/cpu_features.c",
+			Size:   2994,
+		},
 	},
 		rows)
 }
diff --git a/codesize/go/codesizeserver/main.go b/codesize/go/codesizeserver/main.go
index 5f18183..d0e84da 100644
--- a/codesize/go/codesizeserver/main.go
+++ b/codesize/go/codesizeserver/main.go
@@ -189,6 +189,9 @@
 
 	n := now.Now(ctx).UTC()
 	dirs := fileutil.GetHourlyDirs("", n.Add(-daysToPreload*24*time.Hour), n)
+	if *baseapp.Local {
+		dirs = fileutil.GetHourlyDirs("", n.Add(-8*time.Hour), n)
+	}
 	sklog.Debugf("Preloading data, starting in folder %s", dirs[0])
 	for _, dir := range dirs {
 		err := s.gcsClient.AllFilesInDirectory(ctx, dir, func(item *storage.ObjectAttrs) error {