Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove timestamp allocs #254

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

bmizerany
Copy link

When using gogofaster all of my allocations went away except for stdtime fields. This fixes that. The bench results are in the commit message.

@awalterschulze
Copy link
Member

awalterschulze commented Jan 22, 2017 via email

@awalterschulze
Copy link
Member

Basically creating a Timestamp just to Unmarshal it and then convert to another type is a very slow way to simply unmarshal to ints into a time.Time struct.
I just did this to get things working and now that there is ample interest an optimization is warranted.
But we don't need to use any syncing, we can go even faster.

A function can be written to return two ints instead of unmarshaling into an object.
And then these ints can be placed into the time.Time struct.
This should also get rid of the allocs.

You can also turn your benchmark into a test that fails it any allocs occur.

@bmizerany
Copy link
Author

Noted. I'll look into this tomorrow.

benchmark                       old ns/op     new ns/op     delta
BenchmarkStdTimeUnmarshal-4     41.5          18.1          -56.39%

benchmark                       old allocs     new allocs     delta
BenchmarkStdTimeUnmarshal-4     1              0              -100.00%

benchmark                       old bytes     new bytes     delta
BenchmarkStdTimeUnmarshal-4     16            0             -100.00%
@bmizerany
Copy link
Author

Okay. Took a quick stab at this tonight and got close to a 10x speed increase after replacing the sync.Pool with a custom function to unmarshal the data. I started to thing making a custom function would/cloud break unmarshaling if anything changed in timestamp.proto since it wouldn't get any updates the generated code would but I concluded that it is unlikely it will change. If anything does break there are enough tests in here to catch it I suppose.

Full disclosure: I copied much of a code from the generated source in timestamp.go which I was a bit hesitant to do but as I began handwriting it looked very similar so I figured... meh.

}

func TestStdTimeUnmarshalAllocs(t *testing.T) {
data, err := StdTimeMarshal(time.Time{})
Copy link
Member

Choose a reason for hiding this comment

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

how about using NewPopulatedTime, instead of an empty time?

Copy link
Author

Choose a reason for hiding this comment

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

I'll add another AllocsPer with a time.Now() to prove allocs don't happen for both the zero value and non-zero.

@@ -135,3 +135,37 @@ func TestTimestampString(t *testing.T) {
func utcDate(year, month, day int) time.Time {
return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
}

func BenchmarkStdTimeUnmarshal(b *testing.B) {
data, err := StdTimeMarshal(time.Time{})
Copy link
Member

Choose a reason for hiding this comment

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

NewPopulated and maybe make a few in a slice, if possible?

Is RunParallel necessary?

Copy link
Author

Choose a reason for hiding this comment

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

What benefit do we get from randomly generated Times? What do you suggest we do with the slice of Times? RunParallel is not necessary and I'll remove.

Copy link
Author

Choose a reason for hiding this comment

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

I added a non-zero time to the bench and remove RunParallel.

@awalterschulze
Copy link
Member

Optional:

  • What about Duration
  • What about Marshaling
  • Add yourself to the CONTRIBUTORS or AUTHORS as appropriate

@bmizerany
Copy link
Author

I think Duration, Marshaling, etc are better done in another PR to prevent this one from living too long. I'll be getting to those soon when my forcing function kicks in.

@bmizerany
Copy link
Author

I believe I've address all of your concerns about the current patch. It would be nice to get this merged and I'm happy to send over Marshaling and Duration in sperate future PRs.

@awalterschulze
Copy link
Member

Ok maybe we can at least take on the Marshal of the timestamp in this commit as well.
It is doing TimestampProto twice. It should be horribly inefficient.

@awalterschulze
Copy link
Member

hello?

@timpalpant
Copy link

Can I pick this up? I'm in the same situation re: allocs due to StdTime fields. I will implement the marshaling and Duration equivalents if you're still ok with this approach.

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