Skip to content

Proposal for generics-based Setter#201

Draft
medge-mailgun wants to merge 4 commits intomasterfrom
setter-generics
Draft

Proposal for generics-based Setter#201
medge-mailgun wants to merge 4 commits intomasterfrom
setter-generics

Conversation

@medge-mailgun
Copy link
Copy Markdown
Contributor

@medge-mailgun medge-mailgun commented Sep 18, 2024

Using generics, it should now be possible to achieve setter functionality without reflection. If accepted, original methods will be marked as Deprecated but remain for existing usage.

A major change here is that slices and maps do not work with the setter.Default() method. setter.Slice() has been added thus far. setter.Map() has proven interesting to do effectively and usage within Mailgun has not yet been found.

Edit: while this was not done for performance reasons, rather as an attempt to simplify implementation code, here are the comparisons between approaches:

Running on an M3 Macbook yields the following benchmark results:

go test -bench="BenchmarkSetter*" -benchmem -count=10 -tags holster_test_mode -run="^$" ./...

goos: darwin
goarch: arm64
pkg: github.com/mailgun/holster/v4/setter
BenchmarkSetterNew-12    	1000000000	         0.9060 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9524 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9062 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9053 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9059 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9024 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9057 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9052 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9054 ns/op.       0 B/op	       0 allocs/op
BenchmarkSetterNew-12    	1000000000	         0.9056 ns/op	       0 B/op	       0 allocs/op

BenchmarkSetter-12       	210037180	         5.647 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	213309236	         5.626 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	210853106	         5.648 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	211399341	         5.635 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	213350558	         5.690 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	213267204	         5.671 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	210416016	         5.672 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	210588644	         5.678 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	210472189	         5.790 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12       	212123646	         5.683 ns/op	       0 B/op	       0 allocs/op

Updated benchmarks with a Slice test added:

goos: darwin
goarch: arm64
pkg: github.com/mailgun/holster/v4/setter
BenchmarkSetterNew-12          	1000000000	         0.9063 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9057 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9063 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9061 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9064 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9054 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9047 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9048 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9064 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew-12          	1000000000	         0.9060 ns/op	       0 B/op	       0 allocs/op

BenchmarkSetter-12             	213260366	         5.625 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	212896548	         5.636 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	211280826	         5.614 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	212247787	         5.660 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	211494753	         5.642 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	211180790	         5.643 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	211073300	         5.649 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	211085336	         5.660 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	205125676	         5.782 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetter-12             	205552485	         5.777 ns/op	       0 B/op	       0 allocs/op

BenchmarkSetterNew_Slice-12    	415313892	         2.892 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	414445138	         2.890 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	414308188	         2.894 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	413750835	         2.897 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	414357903	         2.888 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	414068553	         2.893 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	414783637	         2.894 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	413121838	         2.910 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	414325414	         3.040 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetterNew_Slice-12    	414430587	         2.892 ns/op	       0 B/op	       0 allocs/op

BenchmarkSetter_Slice-12       	18901965	        62.86 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	18860769	        62.71 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	19149100	        62.84 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	19035922	        62.91 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	18961514	        62.92 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	18966596	        62.92 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	18814023	        63.76 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	18702063	        63.67 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	18443803	        63.64 ns/op	     112 B/op	       4 allocs/op
BenchmarkSetter_Slice-12       	18936728	        63.31 ns/op	     112 B/op	       4 allocs/op

@thrawn01
Copy link
Copy Markdown
Contributor

thrawn01 commented Sep 18, 2024 via email

@medge-mailgun
Copy link
Copy Markdown
Contributor Author

medge-mailgun commented Sep 18, 2024

@thrawn01 good to know! The change was mostly intended to be a code reduction change vs. a performance improvement, for sure. The benchmark was added purely for curiosity's sake 🙏
Caveat, of course, is that this doesn't seem to work for Slices and Maps, so may be less of a code reduction than originally hoped 😓

Comment thread setter/setter.go
Comment thread setter/setter_test.go
assert.Equal(t, false, setter.IsZeroNew(thing))
}

// Not possible now given compiler warnings
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what Go version?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point - this change would not work pre-Go generics, as far as I am aware. So Go 1.18+?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not running it in Go 1.18 - https://github.com/mailgun/holster/blob/master/.github/workflows/test.yaml#L19-L20

Are you seeing these warnings on your local env?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. And that's why these tests are commented out. It's not possible to do what these tests did previously with the new methods. That's what its demonstrating 👀

Mind you, the name of the methods changed. I can fix that

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And to be explicit: this test was previously trying to assign an int to a string, which you technically could do in the original method. The generics form doesn't allow that. It's a compilation error

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And to be explicit: this test was previously trying to assign an int to a string, which you technically could do in the original method. The generics form doesn't allow that. It's a compilation error

I got it now.

Yeah, we don't need them at all, please remove the commented code. https://kentcdodds.com/blog/please-dont-commit-commented-out-code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, all that will be removed once we settle on the PR final form 👍 I just left them there as a note to reviewers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants