Check-in [1f73d90f65]
Overview
Comment:The decompressor now tries to fill in the whole output buffer in a single call.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1f73d90f65ec364f62075e5c5a5b0666be2b116b
User & Date: spaskalev on 2014-12-21 23:24:04
Other Links: manifest | tags
Context
2014-12-22
16:41
Integrate the decompressor2 branch into trunk now that it is faster. check-in: 6d10a1d28f user: spaskalev tags: trunk
2014-12-21
23:24
The decompressor now tries to fill in the whole output buffer in a single call. check-in: 1f73d90f65 user: spaskalev tags: trunk
22:52
Removed TODOs, renamed readCount->rc, wrapped->reader check-in: 630530df49 user: spaskalev tags: trunk
Changes

Modified src/0dev.org/predictor/predictor.go from [090d2f3fd4] to [9dfe9174f8].

   120    120   // and decompresses data according to the predictor algorithm
   121    121   func Decompressor(reader io.Reader) io.Reader {
   122    122   	var ctx context
   123    123   	ctx.input = make([]byte, 0, 8)
   124    124   
   125    125   	return decompressor(func(output []byte) (int, error) {
   126    126   		var (
   127         -			err       error
   128         -			flags     byte
   129         -			rc, total int
          127  +			err          error
          128  +			flags        byte
          129  +			i, rc, total int
   130    130   		)
   131    131   
   132    132   		// Sanity check for space to read into
   133    133   		if len(output) == 0 {
   134    134   			return 0, nil
   135    135   		}
   136    136   
................................................................................
   141    141   			// Check whether we still have leftover data in the buffer :)
   142    142   			if rc < len(ctx.input) {
   143    143   				ctx.input = ctx.input[:copy(ctx.input, ctx.input[rc:])]
   144    144   			}
   145    145   			return rc, nil
   146    146   		}
   147    147   
          148  +	loop:
   148    149   		// Read the flags
   149    150   		rc, err = reader.Read(ctx.input[:1])
   150         -		if rc == 0 || (err != nil && err != io.EOF) {
   151         -			return rc, err
          151  +		if err != nil && err != io.EOF {
          152  +			return 0, err
          153  +		}
          154  +		if rc == 0 {
          155  +			return total, err
   152    156   		}
   153    157   
   154    158   		ctx.input = ctx.input[:8]
   155    159   		flags = ctx.input[0]
   156    160   
   157         -		var i uint = 0
   158         -		for ; i < 8; i++ {
   159         -			if flags&(1<<i) > 0 {
          161  +		for i = 0; i < 8; i++ {
          162  +			if flags&(1<<uint(i)) > 0 {
   160    163   				// Guess was right
   161    164   				ctx.input[i] = ctx.table[ctx.hash]
   162    165   			} else {
   163    166   				rc, err = reader.Read(ctx.input[i:(i + 1)])
   164    167   
   165    168   				if err == io.EOF {
   166    169   					break
   167    170   				}
   168    171   
   169    172   				if err != nil {
   170         -					return rc, err
          173  +					return total, err
   171    174   				}
   172    175   
   173    176   				if rc == 0 { // treat as EoF
   174    177   					break
   175    178   				}
   176    179   
   177    180   				ctx.table[ctx.hash] = ctx.input[i]
   178    181   			}
   179    182   
   180    183   			ctx.hash = (ctx.hash << 4) ^ uint16(ctx.input[i])
   181    184   		}
   182    185   
   183    186   		rc = copy(output, ctx.input[:i])
   184         -
   185    187   		total += rc
   186    188   
   187    189   		// Place any remaining bytes in the buffer
   188         -		if uint(rc) < i {
          190  +		if rc < i {
   189    191   			ctx.input = ctx.input[:copy(ctx.input, ctx.input[rc:i])]
   190    192   		} else {
          193  +			// Clear the buffer
   191    194   			ctx.input = ctx.input[:0]
          195  +
          196  +			// Advance the output buffer ...
          197  +			output = output[i:]
          198  +			// ... and decompress the next block if there is any space left
          199  +			if len(output) > 0 && err != io.EOF {
          200  +				goto loop
          201  +			}
   192    202   		}
   193    203   
   194    204   		return total, err
   195    205   	})
   196    206   }

Modified src/0dev.org/predictor/predictor_test.go from [dd11cf49de] to [0dde784b22].

   136    136   
   137    137   	// Diff the result against the initial input
   138    138   	delta := diff.Diff(diff.D{len(input), len(decompressed),
   139    139   		func(i, j int) bool { return input[i] == decompressed[j] }})
   140    140   
   141    141   	// Return a well-formated error if any differences are found
   142    142   	if len(delta.Added) > 0 || len(delta.Removed) > 0 {
   143         -		return fmt.Errorf("Unexpected decompressed output %v\ninput:  %#x\ntrace:  %#x\noutput: %#x\n",
   144         -			delta, input, trace, decompressed)
          143  +		return fmt.Errorf("Unexpected decompressed output %v\ninput: (%d) %#x\ntrace: (%d) %#x\noutput: (%d) %#x\n",
          144  +			delta, len(input), input, len(trace), trace, len(decompressed), decompressed)
   145    145   	}
   146    146   
   147    147   	// All is good :)
   148    148   	return nil
   149    149   }