github.com/boki/go-xmp@v1.0.1/test/compress_test.go (about)

     1  // Copyright (c) 2017-2018 Alexander Eichhorn
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"bytes"
    19  	"compress/gzip"
    20  	"encoding/json"
    21  	"io/ioutil"
    22  	"os"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/golang/snappy"
    27  	"github.com/montanaflynn/stats"
    28  
    29  	_ "trimmer.io/go-xmp/models"
    30  	"trimmer.io/go-xmp/xmp"
    31  )
    32  
    33  // Compression tests
    34  //
    35  
    36  type TestStats struct {
    37  	OrigSizes         []int
    38  	XmpSizes          []int
    39  	JsonSizes         []int
    40  	ReadTimes         []time.Duration
    41  	JsonTimes         []time.Duration
    42  	XmpTimes          []time.Duration
    43  	XmpGzipSizes      []int
    44  	XmpGzipTimes      []time.Duration
    45  	XmpGunzipTimes    []time.Duration
    46  	JsonGzipSizes     []int
    47  	JsonGzipTimes     []time.Duration
    48  	JsonGunzipTimes   []time.Duration
    49  	XmpSnappySizes    []int
    50  	XmpSnappyTimes    []time.Duration
    51  	XmpUnsnappyTimes  []time.Duration
    52  	JsonSnappySizes   []int
    53  	JsonSnappyTimes   []time.Duration
    54  	JsonUnsnappyTimes []time.Duration
    55  }
    56  
    57  func newStats() *TestStats {
    58  	return &TestStats{
    59  		OrigSizes:         make([]int, len(testfiles)),
    60  		XmpSizes:          make([]int, len(testfiles)),
    61  		JsonSizes:         make([]int, len(testfiles)),
    62  		ReadTimes:         make([]time.Duration, len(testfiles)),
    63  		JsonTimes:         make([]time.Duration, len(testfiles)),
    64  		XmpTimes:          make([]time.Duration, len(testfiles)),
    65  		XmpGzipSizes:      make([]int, len(testfiles)),
    66  		XmpGzipTimes:      make([]time.Duration, len(testfiles)),
    67  		XmpGunzipTimes:    make([]time.Duration, len(testfiles)),
    68  		JsonGzipSizes:     make([]int, len(testfiles)),
    69  		JsonGzipTimes:     make([]time.Duration, len(testfiles)),
    70  		JsonGunzipTimes:   make([]time.Duration, len(testfiles)),
    71  		XmpSnappySizes:    make([]int, len(testfiles)),
    72  		XmpSnappyTimes:    make([]time.Duration, len(testfiles)),
    73  		XmpUnsnappyTimes:  make([]time.Duration, len(testfiles)),
    74  		JsonSnappySizes:   make([]int, len(testfiles)),
    75  		JsonSnappyTimes:   make([]time.Duration, len(testfiles)),
    76  		JsonUnsnappyTimes: make([]time.Duration, len(testfiles)),
    77  	}
    78  }
    79  
    80  func TestCompression(T *testing.T) {
    81  
    82  	st := newStats()
    83  
    84  	// run tests
    85  	for i, v := range testfiles {
    86  		f, err := os.Open(v)
    87  		if err != nil {
    88  			T.Errorf("Cannot open sample '%s': %v", v, err)
    89  		}
    90  		if s, err := f.Stat(); err == nil {
    91  			st.OrigSizes[i] = int(s.Size())
    92  		}
    93  
    94  		start := time.Now()
    95  		d := xmp.NewDecoder(f)
    96  		doc := &xmp.Document{}
    97  		if err := d.Decode(doc); err != nil {
    98  			T.Errorf("%s: %v", v, err)
    99  		}
   100  		f.Close()
   101  		st.ReadTimes[i] = time.Since(start)
   102  
   103  		// JSON target
   104  		start = time.Now()
   105  		buf, _ = json.Marshal(doc)
   106  		st.JsonTimes[i] = time.Since(start)
   107  		st.JsonSizes[i] = len(buf)
   108  		buf, st.JsonGzipSizes[i], st.JsonGzipTimes[i] = gz(T, buf)
   109  		st.JsonGunzipTimes[i] = gunzip(T, buf)
   110  		buf, st.JsonSnappySizes[i], st.JsonSnappyTimes[i] = snap(T, buf)
   111  		st.JsonUnsnappyTimes[i] = unsnap(T, buf)
   112  
   113  		// XMP target
   114  		start = time.Now()
   115  		buf, _ := xmp.Marshal(doc)
   116  		st.XmpTimes[i] = time.Since(start)
   117  		st.XmpSizes[i] = len(buf)
   118  		buf, st.XmpGzipSizes[i], st.XmpGzipTimes[i] = gz(T, buf)
   119  		st.XmpGunzipTimes[i] = gunzip(T, buf)
   120  		buf, st.XmpSnappySizes[i], st.XmpSnappyTimes[i] = snap(T, buf)
   121  		st.XmpUnsnappyTimes[i] = unsnap(T, buf)
   122  
   123  		doc.Close()
   124  	}
   125  
   126  	// summarize result
   127  	T.Logf("Compression Results %d        mean               min                  max\n", len(testfiles))
   128  	T.Logf("-----------------------------------------------------------------------------\n")
   129  	printStats(T, "Original sizes", st.OrigSizes, st.OrigSizes)
   130  	printStats(T, "XMP sizes", st.XmpSizes, st.OrigSizes)
   131  	printStats(T, "XMP Gzip sizes", st.XmpGzipSizes, st.OrigSizes)
   132  	printStats(T, "XMP Snappy sizes", st.XmpSnappySizes, st.OrigSizes)
   133  	printStats(T, "JSON sizes", st.JsonSizes, st.OrigSizes)
   134  	printStats(T, "JSON Gzip sizes", st.JsonGzipSizes, st.OrigSizes)
   135  	printStats(T, "JSON Snappy sizes", st.JsonSnappySizes, st.OrigSizes)
   136  	T.Logf("-----------------------------------------------------------------------------\n")
   137  	printTimes(T, "XML->XMP times", st.ReadTimes)
   138  	printTimes(T, "XMP->JSON times", st.JsonTimes)
   139  	printTimes(T, "XMP->XML times", st.XmpTimes)
   140  	printTimes(T, "XMP Gzip times", st.XmpGzipTimes)
   141  	printTimes(T, "XMP Gunzip times", st.XmpGunzipTimes)
   142  	printTimes(T, "XMP Snappy times", st.XmpSnappyTimes)
   143  	printTimes(T, "XMP Unsnappy times", st.XmpUnsnappyTimes)
   144  	printTimes(T, "JSON Gzip times", st.JsonGzipTimes)
   145  	printTimes(T, "JSON Gunzip times", st.JsonGunzipTimes)
   146  	printTimes(T, "JSON Snappy times", st.JsonSnappyTimes)
   147  	printTimes(T, "JSON Unsnappy times", st.JsonUnsnappyTimes)
   148  }
   149  
   150  func gz(T *testing.T, b []byte) ([]byte, int, time.Duration) {
   151  	start := time.Now()
   152  	var buf bytes.Buffer
   153  	zw := gzip.NewWriter(&buf)
   154  	_, err := zw.Write(b)
   155  	if err != nil {
   156  		T.Error(err)
   157  	}
   158  	if err := zw.Close(); err != nil {
   159  		T.Error(err)
   160  	}
   161  	return buf.Bytes(), buf.Len(), time.Since(start)
   162  }
   163  
   164  func gunzip(T *testing.T, b []byte) time.Duration {
   165  	start := time.Now()
   166  	buf := bytes.NewBuffer(b)
   167  	r, err := gzip.NewReader(buf)
   168  	if err != nil {
   169  		T.Error(err)
   170  	}
   171  	defer r.Close()
   172  	_, err = ioutil.ReadAll(r)
   173  	if err != nil {
   174  		T.Error(err)
   175  	}
   176  	return time.Since(start)
   177  }
   178  
   179  func snap(T *testing.T, b []byte) ([]byte, int, time.Duration) {
   180  	start := time.Now()
   181  	var buf bytes.Buffer
   182  	sw := snappy.NewBufferedWriter(&buf)
   183  	_, err := sw.Write(b)
   184  	if err != nil {
   185  		T.Error(err)
   186  	}
   187  	if err := sw.Close(); err != nil {
   188  		T.Error(err)
   189  	}
   190  	return buf.Bytes(), buf.Len(), time.Since(start)
   191  }
   192  
   193  func unsnap(T *testing.T, b []byte) time.Duration {
   194  	start := time.Now()
   195  	buf := bytes.NewBuffer(b)
   196  	r := snappy.NewReader(buf)
   197  	_, err := ioutil.ReadAll(r)
   198  	if err != nil {
   199  		T.Error(err)
   200  	}
   201  	return time.Since(start)
   202  }
   203  
   204  func printStats(T *testing.T, s string, v, o []int) {
   205  	pct := make([]float64, len(v))
   206  	for i, l := 0, len(v); i < l; i++ {
   207  		pct[i] = float64(v[i]) * 100 / float64(o[i])
   208  	}
   209  	val := stats.LoadRawData(v)
   210  	pval := stats.LoadRawData(pct)
   211  	mean, _ := val.Mean()
   212  	max, _ := val.Max()
   213  	min, _ := val.Min()
   214  	pmean, _ := pval.Mean()
   215  	pmax, _ := pval.Max()
   216  	pmin, _ := pval.Min()
   217  	T.Logf("%20s %10d (%5.1f) %10d (%5.1f) %10d (%5.1f)", s, int(mean), pmean, int(min), pmin, int(max), pmax)
   218  }
   219  
   220  func printTimes(T *testing.T, s string, v []time.Duration) {
   221  	val := stats.LoadRawData(v)
   222  	mean, _ := val.Mean()
   223  	max, _ := val.Max()
   224  	min, _ := val.Min()
   225  	T.Logf("%20s %18v %18v %18v", s, time.Duration(mean), time.Duration(min), time.Duration(max))
   226  }