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 }