1
0
mirror of https://github.com/golang/go synced 2024-11-19 00:44:40 -07:00

os/user: cache the result of user.Current

This has a notable impact on systems with very large passwd files.

Before:
BenchmarkCurrent-12    	   30000	     42546 ns/op

After:
BenchmarkCurrent-12    	20000000	        77.5 ns/op

Saved in perf dashboard:
https://perf.golang.org/search?q=upload:20170206.1

Fixes #11625

Change-Id: Iebc9bf122cc64a4cab24ac06843c7b2bc450ded9
Reviewed-on: https://go-review.googlesource.com/36391
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Sameer Ajmani 2017-02-06 13:21:57 -05:00
parent fd37b8ccf2
commit 2ca5d105b0
2 changed files with 27 additions and 1 deletions

View File

@ -4,20 +4,40 @@
package user
import "sync"
// Current returns the current user.
func Current() (*User, error) {
return current()
cache.Do(func() { cache.u, cache.err = current() })
if cache.err != nil {
return nil, cache.err
}
u := *cache.u // copy
return &u, nil
}
// cache of the current user
var cache struct {
sync.Once
u *User
err error
}
// Lookup looks up a user by username. If the user cannot be found, the
// returned error is of type UnknownUserError.
func Lookup(username string) (*User, error) {
if u, err := Current(); err == nil && u.Username == username {
return u, err
}
return lookupUser(username)
}
// LookupId looks up a user by userid. If the user cannot be found, the
// returned error is of type UnknownUserIdError.
func LookupId(uid string) (*User, error) {
if u, err := Current(); err == nil && u.Uid == uid {
return u, err
}
return lookupUserId(uid)
}

View File

@ -31,6 +31,12 @@ func TestCurrent(t *testing.T) {
}
}
func BenchmarkCurrent(b *testing.B) {
for i := 0; i < b.N; i++ {
Current()
}
}
func compare(t *testing.T, want, got *User) {
if want.Uid != got.Uid {
t.Errorf("got Uid=%q; want %q", got.Uid, want.Uid)