From 7a2eb22e948ba315522f855ee18bad2c2ff99e28 Mon Sep 17 00:00:00 2001 From: Andrew Lytvynov Date: Wed, 20 Dec 2023 09:12:26 -0600 Subject: [PATCH] ipn: remove use of reflect.MethodByName (#10652) Using reflect.MethodByName disables some linked deadcode optimizations and makes our binaries much bigger. Difference before/after this commit: ``` -rwxr-xr-x 1 awly awly 30M Dec 19 15:28 tailscaled.after* -rwxr-xr-x 1 awly awly 43M Dec 19 15:27 tailscaled.before* ``` Fixes #10627 Signed-off-by: Andrew Lytvynov --- ipn/prefs.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/ipn/prefs.go b/ipn/prefs.go index afa8c1cd0..866de18e2 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -414,12 +414,20 @@ func (m *MaskedPrefs) Pretty() string { continue } mpf := mpv.Field(i - 1) - prettyFn := mf.MethodByName("Pretty") - if !prettyFn.IsValid() { - panic(fmt.Sprintf("MaskedPrefs field %q is missing the Pretty method", name)) + // This would be much simpler with reflect.MethodByName("Pretty"), + // but using MethodByName disables some linker optimizations and + // makes our binaries much larger. See + // https://github.com/tailscale/tailscale/issues/10627#issuecomment-1861211945 + // + // Instead, have this explicit switch by field name to do type + // assertions. + switch name { + case "AutoUpdateSet": + p := mf.Interface().(AutoUpdatePrefsMask).Pretty(mpf.Interface().(AutoUpdatePrefs)) + fmt.Fprintf(&sb, "%s={%s}", strings.TrimSuffix(name, "Set"), p) + default: + panic(fmt.Sprintf("unexpected MaskedPrefs field %q", name)) } - res := prettyFn.Call([]reflect.Value{mpf}) - fmt.Fprintf(&sb, "%s={%s}", strings.TrimSuffix(name, "Set"), res[0].String()) } } sb.WriteString("}")