github.com/neilotoole/jsoncolor@v0.6.0/benchmark_test.go (about)

     1  package jsoncolor_test
     2  
     3  import (
     4  	"bytes"
     5  	stdj "encoding/json"
     6  	"io"
     7  	"io/ioutil"
     8  	"testing"
     9  	"time"
    10  
    11  	segmentj "github.com/segmentio/encoding/json"
    12  
    13  	"github.com/neilotoole/jsoncolor"
    14  	nwidgerj "github.com/nwidger/jsoncolor"
    15  )
    16  
    17  func BenchmarkEncode(b *testing.B) {
    18  	recs := makeRecords(b, 10000)
    19  
    20  	benchmarks := []struct {
    21  		name   string
    22  		indent bool
    23  		color  bool
    24  		fn     newEncoderFunc
    25  	}{
    26  		{name: "stdlib_NoIndent", fn: newEncStdlib},
    27  		{name: "stdlib_Indent", fn: newEncStdlib, indent: true},
    28  		{name: "segmentj_NoIndent", fn: newEncSegmentj},
    29  		{name: "segmentj_Indent", fn: newEncSegmentj, indent: true},
    30  		{name: "neilotoole_NoIndent_NoColor", fn: newEncNeilotoole},
    31  		{name: "neilotoole_Indent_NoColor", fn: newEncNeilotoole, indent: true},
    32  		{name: "neilotoole_NoIndent_Color", fn: newEncNeilotoole, color: true},
    33  		{name: "neilotoole_Indent_Color", fn: newEncNeilotoole, indent: true, color: true},
    34  		{name: "nwidger_NoIndent_NoColor", fn: newEncNwidger},
    35  		{name: "nwidger_Indent_NoColor", fn: newEncNwidger, indent: true},
    36  		{name: "nwidger_indent_NoIndent_Colo", fn: newEncNwidger, color: true},
    37  		{name: "nwidger_indent_Indent_Color", fn: newEncNwidger, indent: true, color: true},
    38  	}
    39  
    40  	for _, bm := range benchmarks {
    41  		bm := bm
    42  		b.Run(bm.name, func(b *testing.B) {
    43  			b.ReportAllocs()
    44  
    45  			b.ResetTimer()
    46  
    47  			for n := 0; n < b.N; n++ {
    48  				w := &bytes.Buffer{}
    49  				enc := bm.fn(w, bm.indent, bm.color)
    50  
    51  				for i := range recs {
    52  					err := enc.Encode(recs[i])
    53  					if err != nil {
    54  						b.Error(err)
    55  					}
    56  				}
    57  			}
    58  		})
    59  	}
    60  }
    61  
    62  func makeRecords(tb testing.TB, n int) [][]interface{} {
    63  	recs := make([][]interface{}, 0, n)
    64  
    65  	// add a bunch of data from a file, just to make the recs bigger
    66  	data, err := ioutil.ReadFile("testdata/sakila_actor.json")
    67  	if err != nil {
    68  		tb.Fatal(err)
    69  	}
    70  
    71  	f := new(interface{})
    72  	if err = stdj.Unmarshal(data, f); err != nil {
    73  		tb.Fatal(err)
    74  	}
    75  
    76  	type someStruct struct {
    77  		i int64
    78  		a string
    79  		f interface{} // x holds JSON loaded from file
    80  	}
    81  
    82  	for i := 0; i < n; i++ {
    83  		rec := []interface{}{
    84  			int(1),
    85  			int64(2),
    86  			float32(2.71),
    87  			float64(3.14),
    88  			"hello world",
    89  			someStruct{i: 8, a: "goodbye world", f: f},
    90  			map[string]interface{}{"a": 9, "b": "ca va"},
    91  			true,
    92  			false,
    93  			time.Unix(1631659220, 0),
    94  			time.Millisecond * 1631659220,
    95  		}
    96  		recs = append(recs, rec)
    97  	}
    98  
    99  	return recs
   100  }
   101  
   102  type newEncoderFunc func(w io.Writer, indent, color bool) encoder
   103  
   104  var (
   105  	_ newEncoderFunc = newEncStdlib
   106  	_ newEncoderFunc = newEncSegmentj
   107  	_ newEncoderFunc = newEncNeilotoole
   108  	_ newEncoderFunc = newEncNwidger
   109  )
   110  
   111  type encoder interface {
   112  	SetEscapeHTML(on bool)
   113  	SetIndent(prefix, indent string)
   114  	Encode(v interface{}) error
   115  }
   116  
   117  func newEncStdlib(w io.Writer, indent, color bool) encoder {
   118  	enc := stdj.NewEncoder(w)
   119  	if indent {
   120  		enc.SetIndent("", "  ")
   121  	}
   122  	enc.SetEscapeHTML(true)
   123  	return enc
   124  }
   125  
   126  func newEncSegmentj(w io.Writer, indent, color bool) encoder {
   127  	enc := segmentj.NewEncoder(w)
   128  	if indent {
   129  		enc.SetIndent("", "  ")
   130  	}
   131  	enc.SetEscapeHTML(true)
   132  	return enc
   133  }
   134  
   135  func newEncNeilotoole(w io.Writer, indent, color bool) encoder {
   136  	enc := jsoncolor.NewEncoder(w)
   137  	if indent {
   138  		enc.SetIndent("", "  ")
   139  	}
   140  	enc.SetEscapeHTML(true)
   141  
   142  	if color {
   143  		clrs := jsoncolor.DefaultColors()
   144  		enc.SetColors(clrs)
   145  	}
   146  
   147  	return enc
   148  }
   149  
   150  func newEncNwidger(w io.Writer, indent, color bool) encoder {
   151  	if !color {
   152  		enc := nwidgerj.NewEncoder(w)
   153  		enc.SetEscapeHTML(false)
   154  		if indent {
   155  			enc.SetIndent("", "  ")
   156  		}
   157  		return enc
   158  	}
   159  
   160  	// It's color
   161  	f := nwidgerj.NewFormatter()
   162  	f.SpaceColor = nwidgerj.DefaultSpaceColor
   163  	f.CommaColor = nwidgerj.DefaultCommaColor
   164  	f.ColonColor = nwidgerj.DefaultColonColor
   165  	f.ObjectColor = nwidgerj.DefaultObjectColor
   166  	f.ArrayColor = nwidgerj.DefaultArrayColor
   167  	f.FieldQuoteColor = nwidgerj.DefaultFieldQuoteColor
   168  	f.FieldColor = nwidgerj.DefaultFieldColor
   169  	f.StringQuoteColor = nwidgerj.DefaultStringQuoteColor
   170  	f.StringColor = nwidgerj.DefaultStringColor
   171  	f.TrueColor = nwidgerj.DefaultTrueColor
   172  	f.FalseColor = nwidgerj.DefaultFalseColor
   173  	f.NumberColor = nwidgerj.DefaultNumberColor
   174  	f.NullColor = nwidgerj.DefaultNullColor
   175  
   176  	enc := nwidgerj.NewEncoderWithFormatter(w, f)
   177  	enc.SetEscapeHTML(false)
   178  
   179  	if indent {
   180  		enc.SetIndent("", "  ")
   181  	}
   182  
   183  	return enc
   184  }