From 6d6cffc852d079580a09062100a810dce250d8b0 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sun, 21 Jan 2024 21:55:36 +0100 Subject: [PATCH] Optimize radio item renderer to be 50% faster MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit goos: linux goarch: amd64 pkg: fyne.io/fyne/v2/widget cpu: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ RadioCreateRenderer-8 664.0n ± 2% 351.4n ± 2% -47.09% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ RadioCreateRenderer-8 736.0 ± 0% 704.0 ± 0% -4.35% (p=0.000 n=10) │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ RadioCreateRenderer-8 9.000 ± 0% 4.000 ± 0% -55.56% (p=0.000 n=10) --- widget/radio_item.go | 26 ++++++++------------------ widget/radio_item_test.go | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/widget/radio_item.go b/widget/radio_item.go index 3aab898854..6325635da1 100644 --- a/widget/radio_item.go +++ b/widget/radio_item.go @@ -37,19 +37,8 @@ type radioItem struct { // // Implements: fyne.Widget func (i *radioItem) CreateRenderer() fyne.WidgetRenderer { - focusIndicator := canvas.NewCircle(color.Transparent) - icon := canvas.NewImageFromResource(theme.RadioButtonFillIcon()) - over := canvas.NewImageFromResource(theme.NewThemedResource(theme.RadioButtonIcon())) - label := canvas.NewText(i.Label, theme.ForegroundColor()) - label.Alignment = fyne.TextAlignLeading - r := &radioItemRenderer{ - BaseRenderer: widget.NewBaseRenderer([]fyne.CanvasObject{focusIndicator, icon, over, label}), - focusIndicator: focusIndicator, - icon: icon, - over: over, - item: i, - label: label, - } + r := &radioItemRenderer{item: i, label: canvas.Text{Alignment: fyne.TextAlignLeading}} + r.SetObjects([]fyne.CanvasObject{&r.focusIndicator, &r.icon, &r.over, &r.label}) r.update() return r } @@ -149,11 +138,11 @@ func (i *radioItem) toggle() { type radioItemRenderer struct { widget.BaseRenderer + item *radioItem - focusIndicator *canvas.Circle - icon, over *canvas.Image - item *radioItem - label *canvas.Text + focusIndicator canvas.Circle + icon, over canvas.Image + label canvas.Text } func (r *radioItemRenderer) Layout(size fyne.Size) { @@ -191,10 +180,11 @@ func (r *radioItemRenderer) Refresh() { func (r *radioItemRenderer) update() { r.label.Text = r.item.Label - r.label.Color = theme.ForegroundColor() r.label.TextSize = theme.TextSize() if r.item.Disabled() { r.label.Color = theme.DisabledColor() + } else { + r.label.Color = theme.ForegroundColor() } out := theme.NewThemedResource(theme.RadioButtonIcon()) diff --git a/widget/radio_item_test.go b/widget/radio_item_test.go index b02d229f23..0f63906e14 100644 --- a/widget/radio_item_test.go +++ b/widget/radio_item_test.go @@ -10,6 +10,21 @@ import ( "github.com/stretchr/testify/assert" ) +var globalRadioRenderer fyne.WidgetRenderer + +func BenchmarkRadioCreateRenderer(b *testing.B) { + var renderer fyne.WidgetRenderer + widget := &radioItem{} + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + renderer = widget.CreateRenderer() + } + + // Avoid having the value optimized out by the compiler. + globalRadioRenderer = renderer +} + func TestRadioItem_FocusIndicator_Centered_Vertically(t *testing.T) { item := newRadioItem("Hello", nil) render := test.WidgetRenderer(item).(*radioItemRenderer)