Skip to content

Commit

Permalink
glog: update glog to the latest internal version (#59)
Browse files Browse the repository at this point in the history
This change upstreams a number of changes since the last package update.

In particular this adds:

- New exported APIs (see godoc for further details):
  - glog.VDepth
  - glog.InfoDepthf
  - glog.WarningDepthf
  - glog.ErrorDepthf
  - glog.FatalDepthf
  - glog.ExitDepthf
  - glog.Names
  - glog.NewStandardLogger
  - glog.Verbose.InfoDepth
  - glog.Verbose.InfoDepthf
  - glog.ErrNoLog

- The -log_backtrace_at flag accepts now a comma-separated list of file:line locations.

- The -vmodule flag accepts a new syntax to match the full path to a module instead of just the module name. See the updated package documentation.

- A new internal/logsink package to support other outputs than files. Note: This package is internal, because we cannot guarantee at this point that the API remains stable.

More details at go/log-vs-glog (google-internal).
  • Loading branch information
chressie committed Mar 3, 2023
1 parent 9ef845f commit 115d1f9
Show file tree
Hide file tree
Showing 11 changed files with 2,268 additions and 1,008 deletions.
1,217 changes: 329 additions & 888 deletions glog.go

Large diffs are not rendered by default.

164 changes: 164 additions & 0 deletions glog_bench_test.go
@@ -0,0 +1,164 @@
package glog

import (
"flag"
"io/ioutil"
"runtime"
"sync"
"sync/atomic"
"testing"
"time"
)

// discarder is a flushSyncWriter that discards all data.
// Sync sleeps for 10ms to simulate a disk seek.
type discarder struct {
}

func (d *discarder) Write(data []byte) (int, error) {
return len(data), nil
}

func (d *discarder) Flush() error {
return nil
}

func (d *discarder) Sync() error {
time.Sleep(10 * time.Millisecond)
return nil
}

func (d *discarder) filenames() []string {
return nil
}

// newDiscard sets the log writers to all new byte buffers and returns the old array.
func (s *fileSink) newDiscarders() severityWriters {
return s.swap(severityWriters{new(discarder), new(discarder), new(discarder), new(discarder)})
}

func discardStderr() func() {
se := sinks.stderr.w
sinks.stderr.w = ioutil.Discard
return func() { sinks.stderr.w = se }
}

const message = "benchmark log message"

func benchmarkLog(b *testing.B, log func(...any)) {
defer sinks.file.swap(sinks.file.newDiscarders())
defer discardStderr()()
b.ResetTimer()
for i := 0; i < b.N; i++ {
log(message)
}
b.StopTimer()
}

func benchmarkLogConcurrent(b *testing.B, log func(...any)) {
defer sinks.file.swap(sinks.file.newDiscarders())
defer discardStderr()()
b.ResetTimer()
concurrency := runtime.GOMAXPROCS(0)
var wg sync.WaitGroup
wg.Add(concurrency)
for i := 0; i < concurrency; i++ {
go func() {
for i := 0; i < b.N; i++ {
log(message)
}
wg.Done()
}()
}
wg.Wait()
b.StopTimer()
}

func BenchmarkInfo(b *testing.B) {
benchmarkLog(b, Info)
}

func BenchmarkInfoConcurrent(b *testing.B) {
benchmarkLogConcurrent(b, Info)
}

func BenchmarkWarning(b *testing.B) {
benchmarkLog(b, Warning)
}

func BenchmarkWarningConcurrent(b *testing.B) {
benchmarkLogConcurrent(b, Warning)
}

func BenchmarkError(b *testing.B) {
benchmarkLog(b, Error)
}

func BenchmarkErrorConcurrent(b *testing.B) {
benchmarkLogConcurrent(b, Error)
}

func mixer() func(...any) {
var i int64
return func(args ...any) {
n := atomic.AddInt64(&i, 1)
switch {
case n%10000 == 0:
Error(args...)
case n%1000 == 0:
Warning(args...)
default:
Info(args...)
}
}
}

func BenchmarkMix(b *testing.B) {
benchmarkLog(b, mixer())
}

func BenchmarkMixConcurrent(b *testing.B) {
benchmarkLogConcurrent(b, mixer())
}

func BenchmarkVLogDisabled(b *testing.B) {
benchmarkLog(b, vlog)
}

func BenchmarkVLogDisabledConcurrent(b *testing.B) {
benchmarkLogConcurrent(b, vlog)
}

func BenchmarkVLogModuleFlagSet(b *testing.B) {
defer withVmodule("nonexistant=5")()
benchmarkLog(b, vlog)
}

func BenchmarkVLogModuleFlagSetConcurrent(b *testing.B) {
defer withVmodule("nonexistant=5")()
benchmarkLogConcurrent(b, vlog)
}

func BenchmarkVLogEnabled(b *testing.B) {
defer withVmodule("glog_bench_test=5")()
if got := bool(V(3)); got != true {
b.Fatalf("V(3) == %v, want %v", got, true)
}
benchmarkLog(b, vlog)
}

func BenchmarkVLogEnabledConcurrent(b *testing.B) {
defer withVmodule("glog_bench_test=5")()
benchmarkLogConcurrent(b, vlog)
}

func vlog(args ...any) {
V(3).Info(args)
}

func withVmodule(val string) func() {
if err := flag.Set("vmodule", val); err != nil {
panic(err)
}
return func() { flag.Set("vmodule", "") }
}

0 comments on commit 115d1f9

Please sign in to comment.