github.com/janelia-flyem/dvid@v1.0.0/datatype/common/labels/compressed_test.go (about)

     1  package labels
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"encoding/binary"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"math/rand"
    10  	"os"
    11  	"path/filepath"
    12  	"runtime"
    13  	"testing"
    14  
    15  	"github.com/janelia-flyem/dvid/dvid"
    16  	lz4 "github.com/janelia-flyem/go/golz4-updated"
    17  )
    18  
    19  type testData struct {
    20  	u        []uint64
    21  	b        []byte
    22  	filename string
    23  }
    24  
    25  func (d testData) String() string {
    26  	return filepath.Base(d.filename)
    27  }
    28  
    29  func solidTestData(label uint64) (td testData) {
    30  	numVoxels := 64 * 64 * 64
    31  	td.u = make([]uint64, numVoxels)
    32  	td.b = dvid.AliasUint64ToByte(td.u)
    33  	td.filename = fmt.Sprintf("solid volume of label %d", label)
    34  	for i := 0; i < numVoxels; i++ {
    35  		td.u[i] = label
    36  	}
    37  	return
    38  }
    39  
    40  var testFiles = []string{
    41  	"../../../test_data/fib19-64x64x64-sample1.dat.gz",
    42  	"../../../test_data/fib19-64x64x64-sample2.dat.gz",
    43  	"../../../test_data/cx-64x64x64-sample1.dat.gz",
    44  	"../../../test_data/cx-64x64x64-sample2.dat.gz",
    45  }
    46  
    47  func loadData(filename string) (td testData, err error) {
    48  	td.b, err = readGzipFile(filename)
    49  	if err != nil {
    50  		return
    51  	}
    52  	td.u, err = dvid.AliasByteToUint64(td.b)
    53  	if err != nil {
    54  		return
    55  	}
    56  	td.filename = filename
    57  	return
    58  }
    59  
    60  func loadTestData(t *testing.T, filename string) (td testData) {
    61  	var err error
    62  	td.b, err = readGzipFile(filename)
    63  	if err != nil {
    64  		t.Fatalf("unable to open test data file %q: %v\n", filename, err)
    65  	}
    66  	td.u, err = dvid.AliasByteToUint64(td.b)
    67  	if err != nil {
    68  		t.Fatalf("unable to create alias []uint64 for data file %q: %v\n", filename, err)
    69  	}
    70  	td.filename = filename
    71  	return
    72  }
    73  
    74  func readGzipFile(filename string) ([]byte, error) {
    75  	f, err := os.Open(filename)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	defer f.Close()
    80  
    81  	fz, err := gzip.NewReader(f)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	defer fz.Close()
    86  
    87  	data, err := ioutil.ReadAll(fz)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	return data, nil
    92  }
    93  
    94  func checkBytes(t *testing.T, text string, expected, got []byte) {
    95  	if len(expected) != len(got) {
    96  		t.Errorf("%s byte mismatch: expected %d bytes, got %d bytes\n", text, len(expected), len(got))
    97  	}
    98  	for i, val := range got {
    99  		if expected[i] != val {
   100  			t.Errorf("%s byte mismatch found at index %d, expected %d, got %d\n", text, i, expected[i], val)
   101  			return
   102  		}
   103  	}
   104  }
   105  
   106  func checkLabels(t *testing.T, text string, expected, got []byte) {
   107  	if len(expected) != len(got) {
   108  		t.Errorf("%s byte mismatch: expected %d bytes, got %d bytes\n", text, len(expected), len(got))
   109  	}
   110  	expectLabels, err := dvid.AliasByteToUint64(expected)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  	gotLabels, err := dvid.AliasByteToUint64(got)
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	errmsg := 0
   119  	for i, val := range gotLabels {
   120  		if expectLabels[i] != val {
   121  			_, fn, line, _ := runtime.Caller(1)
   122  			t.Errorf("%s label mismatch found at index %d, expected %d, got %d [%s:%d]\n", text, i, expectLabels[i], val, fn, line)
   123  			errmsg++
   124  			if errmsg > 5 {
   125  				return
   126  			}
   127  		} else if errmsg > 0 {
   128  			t.Errorf("yet no mismatch at index %d, expected %d, got %d\n", i, expectLabels[i], val)
   129  		}
   130  	}
   131  	runtime.KeepAlive(&expected)
   132  	runtime.KeepAlive(&got)
   133  }
   134  
   135  func printRatio(t *testing.T, curDesc string, cur, orig int, compareDesc string, compare int) {
   136  	p1 := 100.0 * float32(cur) / float32(orig)
   137  	p2 := float32(cur) / float32(compare)
   138  	t.Logf("%s compression result: %d (%4.2f%% orig, %4.2f x %s)\n", curDesc, cur, p1, p2, compareDesc)
   139  }
   140  
   141  func blockTest(t *testing.T, d testData) {
   142  	var err error
   143  	var origLZ4Size int
   144  	origLZ4 := make([]byte, lz4.CompressBound(d.b))
   145  	if origLZ4Size, err = lz4.Compress(d.b, origLZ4); err != nil {
   146  		t.Fatal(err)
   147  	}
   148  	printRatio(t, "Orig LZ4", origLZ4Size, len(d.b), "Orig", len(d.b))
   149  
   150  	labels := make(map[uint64]int)
   151  	for _, label := range d.u {
   152  		labels[label]++
   153  	}
   154  	for label, voxels := range labels {
   155  		t.Logf("Label %12d: %8d voxels\n", label, voxels)
   156  	}
   157  
   158  	cseg, err := oldCompressUint64(d.u, dvid.Point3d{64, 64, 64})
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	csegBytes := dvid.AliasUint32ToByte(cseg)
   163  	block, err := MakeBlock(d.b, dvid.Point3d{64, 64, 64})
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  	dvidBytes, _ := block.MarshalBinary()
   168  
   169  	printRatio(t, "Goog", len(csegBytes), len(d.b), "DVID", len(dvidBytes))
   170  	printRatio(t, "DVID", len(dvidBytes), len(d.b), "Goog", len(csegBytes))
   171  
   172  	var gzipOut bytes.Buffer
   173  	zw := gzip.NewWriter(&gzipOut)
   174  	if _, err = zw.Write(csegBytes); err != nil {
   175  		t.Fatal(err)
   176  	}
   177  	zw.Flush()
   178  	runtime.KeepAlive(&cseg)
   179  	csegGzip := make([]byte, gzipOut.Len())
   180  	copy(csegGzip, gzipOut.Bytes())
   181  	gzipOut.Reset()
   182  	if _, err = zw.Write(dvidBytes); err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	zw.Flush()
   186  	dvidGzip := make([]byte, gzipOut.Len())
   187  	copy(dvidGzip, gzipOut.Bytes())
   188  
   189  	printRatio(t, "Goog GZIP", len(csegGzip), len(d.b), "DVID GZIP", len(dvidGzip))
   190  	printRatio(t, "DVID GZIP", len(dvidGzip), len(d.b), "Goog GZIP", len(csegGzip))
   191  
   192  	var csegLZ4Size, dvidLZ4Size int
   193  	csegLZ4 := make([]byte, lz4.CompressBound(csegBytes))
   194  	if csegLZ4Size, err = lz4.Compress(csegBytes, csegLZ4); err != nil {
   195  		t.Fatal(err)
   196  	}
   197  	dvidLZ4 := make([]byte, lz4.CompressBound(dvidBytes))
   198  	if dvidLZ4Size, err = lz4.Compress(dvidBytes, dvidLZ4); err != nil {
   199  		t.Fatal(err)
   200  	}
   201  
   202  	printRatio(t, "Goog LZ4 ", csegLZ4Size, len(d.b), "DVID LZ4 ", dvidLZ4Size)
   203  	printRatio(t, "DVID LZ4 ", dvidLZ4Size, len(d.b), "Goog LZ4 ", csegLZ4Size)
   204  
   205  	// test DVID block output result
   206  	redata, size := block.MakeLabelVolume()
   207  
   208  	if size[0] != 64 || size[1] != 64 || size[2] != 64 {
   209  		t.Errorf("expected DVID compression size to be 64x64x64, got %s\n", size)
   210  	}
   211  	checkLabels(t, "DVID compression", d.b, redata)
   212  
   213  	// make sure the blocks properly Marshal and Unmarshal
   214  	serialization, _ := block.MarshalBinary()
   215  	datacopy := make([]byte, len(serialization))
   216  	copy(datacopy, serialization)
   217  	var block2 Block
   218  	if err := block2.UnmarshalBinary(datacopy); err != nil {
   219  		t.Fatal(err)
   220  	}
   221  	redata2, size2 := block2.MakeLabelVolume()
   222  	if size2[0] != 64 || size2[1] != 64 || size2[2] != 64 {
   223  		t.Errorf("expected DVID compression size to be 64x64x64, got %s\n", size2)
   224  	}
   225  	checkLabels(t, "marshal/unmarshal copy", redata, redata2)
   226  }
   227  
   228  func TestBlockCompression(t *testing.T) {
   229  	solid2serialization := make([]byte, 24)
   230  	binary.LittleEndian.PutUint32(solid2serialization[0:4], 8)
   231  	binary.LittleEndian.PutUint32(solid2serialization[4:8], 8)
   232  	binary.LittleEndian.PutUint32(solid2serialization[8:12], 8)
   233  	binary.LittleEndian.PutUint32(solid2serialization[12:16], 1)
   234  	binary.LittleEndian.PutUint64(solid2serialization[16:24], 2)
   235  	var block Block
   236  	if err := block.UnmarshalBinary(solid2serialization); err != nil {
   237  		t.Fatal(err)
   238  	}
   239  	if block.Value(dvid.Point3d{34, 22, 12}) != 2 {
   240  		t.Errorf("Expected 2, got %d\n", block.Value(dvid.Point3d{34, 22, 12}))
   241  	}
   242  	if block.Value(dvid.Point3d{58, 4, 31}) != 2 {
   243  		t.Errorf("Expected 2, got %d\n", block.Value(dvid.Point3d{58, 4, 31}))
   244  	}
   245  
   246  	solid2, size := block.MakeLabelVolume()
   247  	if !size.Equals(dvid.Point3d{64, 64, 64}) {
   248  		t.Errorf("Expected solid2 block size of %s, got %s\n", "(64,64,64)", size)
   249  	}
   250  	if len(solid2) != 64*64*64*8 {
   251  		t.Errorf("Expected solid2 uint64 array to have 64x64x64x8 bytes, got %d bytes instead", len(solid2))
   252  	}
   253  	uint64array, err := dvid.AliasByteToUint64(solid2)
   254  	if err != nil {
   255  		t.Fatal(err)
   256  	}
   257  	for i := 0; i < 64*64*64; i++ {
   258  		if uint64array[i] != 2 {
   259  			t.Fatalf("Expected solid2 label volume to have all 2's, found %d at pos %d\n", uint64array[i], i)
   260  		}
   261  	}
   262  	runtime.KeepAlive(&solid2)
   263  
   264  	blockTest(t, solidTestData(0))
   265  	blockTest(t, solidTestData(2))
   266  	for _, filename := range testFiles {
   267  		blockTest(t, loadTestData(t, filename))
   268  	}
   269  
   270  	numVoxels := 64 * 64 * 64
   271  	testvol := make([]uint64, numVoxels)
   272  	for i := 0; i < numVoxels; i++ {
   273  		testvol[i] = uint64(i)
   274  	}
   275  
   276  	bptr, err := MakeBlock(dvid.AliasUint64ToByte(testvol), dvid.Point3d{64, 64, 64})
   277  	if err != nil {
   278  		t.Fatalf("error making block: %v\n", err)
   279  	}
   280  	runtime.KeepAlive(&testvol)
   281  	testvol2, size := bptr.MakeLabelVolume()
   282  	if size[0] != 64 || size[1] != 64 || size[2] != 64 {
   283  		t.Fatalf("error in size after making block: %v\n", size)
   284  	}
   285  	checkLabels(t, "block compress/uncompress", dvid.AliasUint64ToByte(testvol), testvol2)
   286  	runtime.KeepAlive(&testvol)
   287  	i := uint64(12*64*64 + 22*64 + 34)
   288  	if bptr.Value(dvid.Point3d{34, 22, 12}) != i {
   289  		t.Errorf("Expected %d, got %d\n", bptr.Value(dvid.Point3d{34, 22, 12}), i)
   290  	}
   291  	i = 31*64*64 + 4*64 + 58
   292  	if bptr.Value(dvid.Point3d{58, 4, 31}) != i {
   293  		t.Errorf("Expected %d, got %d\n", bptr.Value(dvid.Point3d{58, 4, 31}), i)
   294  	}
   295  }
   296  
   297  func TestBlockDownres(t *testing.T) {
   298  	// Test solid blocks
   299  	solidOctants := [8]*Block{
   300  		MakeSolidBlock(3, dvid.Point3d{64, 64, 64}),
   301  		MakeSolidBlock(3, dvid.Point3d{64, 64, 64}),
   302  		MakeSolidBlock(9, dvid.Point3d{64, 64, 64}),
   303  		nil,
   304  		MakeSolidBlock(12, dvid.Point3d{64, 64, 64}),
   305  		MakeSolidBlock(21, dvid.Point3d{64, 64, 64}),
   306  		MakeSolidBlock(83, dvid.Point3d{64, 64, 64}),
   307  		MakeSolidBlock(129, dvid.Point3d{64, 64, 64}),
   308  	}
   309  
   310  	// make reference volume that is downres.
   311  	gt := make([]uint64, 64*64*64)
   312  	for z := 0; z < 32; z++ {
   313  		for y := 0; y < 32; y++ {
   314  			for x := 0; x < 32; x++ {
   315  				// octant (0,0,0)
   316  				i := z*64*64 + y*64 + x
   317  				gt[i] = 3
   318  
   319  				// octant (1,0,0)
   320  				i = z*64*64 + y*64 + x + 32
   321  				gt[i] = 3
   322  
   323  				// octant (0,1,0)
   324  				i = z*64*64 + (y+32)*64 + x
   325  				gt[i] = 9
   326  
   327  				// octant (1,1,0)
   328  				i = z*64*64 + (y+32)*64 + x + 32
   329  				gt[i] = 0
   330  
   331  				// octant (0,0,1)
   332  				i = (z+32)*64*64 + y*64 + x
   333  				gt[i] = 12
   334  
   335  				// octant (1,0,1)
   336  				i = (z+32)*64*64 + y*64 + x + 32
   337  				gt[i] = 21
   338  
   339  				// octant (0,1,1)
   340  				i = (z+32)*64*64 + (y+32)*64 + x
   341  				gt[i] = 83
   342  
   343  				// octant (1,1,1)
   344  				i = (z+32)*64*64 + (y+32)*64 + x + 32
   345  				gt[i] = 129
   346  			}
   347  		}
   348  	}
   349  	gtarr := dvid.AliasUint64ToByte(gt)
   350  
   351  	// run tests using solid block octants
   352  	var b Block
   353  	b.Size = dvid.Point3d{64, 64, 64}
   354  	if err := b.DownresSlow(solidOctants); err != nil {
   355  		t.Fatalf("bad downres: %v\n", err)
   356  	}
   357  	resultBytes, size := b.MakeLabelVolume()
   358  	if !size.Equals(b.Size) {
   359  		t.Fatalf("expected downres block size to be %s, got %s\n", b.Size, size)
   360  	}
   361  	if len(resultBytes) != 64*64*64*8 {
   362  		t.Fatalf("expected downres block volume bytes to be 64^3 * 8, not %d\n", len(resultBytes))
   363  	}
   364  	checkLabels(t, "checking DownresSlow with ground truth", gtarr, resultBytes)
   365  
   366  	var b2 Block
   367  	b2.Size = dvid.Point3d{64, 64, 64}
   368  	if err := b2.Downres(solidOctants); err != nil {
   369  		t.Fatalf("bad downres: %v\n", err)
   370  	}
   371  	resultBytes, size = b2.MakeLabelVolume()
   372  	if !size.Equals(b.Size) {
   373  		t.Fatalf("expected downres block size to be %s, got %s\n", b2.Size, size)
   374  	}
   375  	if len(resultBytes) != 64*64*64*8 {
   376  		t.Fatalf("expected downres block volume bytes to be 64^3 * 8, not %d\n", len(resultBytes))
   377  	}
   378  	checkLabels(t, "checking Downres with ground truth", gtarr, resultBytes)
   379  	runtime.KeepAlive(&gt)
   380  }
   381  
   382  func setLabel(vol []uint64, size, x, y, z int, label uint64) {
   383  	i := z*size*size + y*size + x
   384  	vol[i] = label
   385  }
   386  
   387  func TestSolidBlockRLE(t *testing.T) {
   388  	var buf bytes.Buffer
   389  	lbls := Set{}
   390  	lbls[3] = struct{}{}
   391  	outOp := NewOutputOp(&buf)
   392  	go WriteRLEs(lbls, outOp, dvid.Bounds{})
   393  
   394  	block := MakeSolidBlock(3, dvid.Point3d{64, 64, 64})
   395  	pb := PositionedBlock{
   396  		Block:  *block,
   397  		BCoord: dvid.ChunkPoint3d{2, 1, 2}.ToIZYXString(),
   398  	}
   399  	outOp.Process(&pb)
   400  
   401  	pb2 := PositionedBlock{
   402  		Block:  *block,
   403  		BCoord: dvid.ChunkPoint3d{3, 1, 2}.ToIZYXString(),
   404  	}
   405  	outOp.Process(&pb2)
   406  
   407  	// include a solid half-block so we can make sure RLE pasting across blocks works.
   408  	numVoxels := 64 * 64 * 64
   409  	testvol := make([]uint64, numVoxels)
   410  	for z := 0; z < 64; z++ {
   411  		for y := 0; y < 32; y++ {
   412  			for x := 0; x < 64; x++ {
   413  				i := z*64*64 + y*64 + x
   414  				testvol[i] = 3
   415  			}
   416  		}
   417  	}
   418  	block2, err := MakeBlock(dvid.AliasUint64ToByte(testvol), dvid.Point3d{64, 64, 64})
   419  	if err != nil {
   420  		t.Fatalf("error making block: %v\n", err)
   421  	}
   422  	runtime.KeepAlive(&testvol)
   423  	pts := []dvid.Point3d{dvid.Point3d{10, 10, 10}, dvid.Point3d{40, 40, 40}, dvid.Point3d{58, 58, 58}}
   424  	labels := block2.GetPointLabels(pts)
   425  	if len(labels) != 3 {
   426  		t.Fatalf("expected 3 labels back, got %d\n", len(labels))
   427  	}
   428  	if labels[0] != 3 {
   429  		t.Errorf("Expected pt %s is label 3, got %d\n", pts[0], labels[0])
   430  	}
   431  	if labels[1] != 0 {
   432  		t.Errorf("Expected pt %s is label 0, got %d\n", pts[1], labels[1])
   433  	}
   434  	if labels[2] != 0 {
   435  		t.Errorf("Expected pt %s is label 0, got %d\n", pts[2], labels[2])
   436  	}
   437  	pb3 := PositionedBlock{
   438  		Block:  *block2,
   439  		BCoord: dvid.ChunkPoint3d{4, 1, 2}.ToIZYXString(),
   440  	}
   441  	outOp.Process(&pb3)
   442  
   443  	if err := outOp.Finish(); err != nil {
   444  		t.Fatalf("error writing RLEs: %v\n", err)
   445  	}
   446  	output, err := ioutil.ReadAll(&buf)
   447  	if err != nil {
   448  		t.Fatalf("error on reading WriteRLEs: %v\n", err)
   449  	}
   450  
   451  	expectedNumRLEs := 64 * 64 * 16
   452  	if len(output) != expectedNumRLEs {
   453  		t.Fatalf("expected %d RLEs (%d bytes), got %d bytes\n", expectedNumRLEs/16, expectedNumRLEs, len(output))
   454  	}
   455  	var rles dvid.RLEs
   456  	if err = rles.UnmarshalBinary(output); err != nil {
   457  		t.Fatalf("unable to parse binary RLEs: %v\n", err)
   458  	}
   459  	var i int
   460  	expected := make(dvid.RLEs, 64*64)
   461  	for z := int32(0); z < 64; z++ {
   462  		for y := int32(0); y < 32; y++ {
   463  			expected[i] = dvid.NewRLE(dvid.Point3d{128, y + 64, z + 128}, 192)
   464  			i++
   465  		}
   466  	}
   467  	for z := int32(0); z < 64; z++ {
   468  		for y := int32(32); y < 64; y++ {
   469  			expected[i] = dvid.NewRLE(dvid.Point3d{128, y + 64, z + 128}, 128)
   470  			i++
   471  		}
   472  	}
   473  	expected = expected.Normalize()
   474  	for i, rle := range rles.Normalize() {
   475  		if rle != expected[i] {
   476  			t.Errorf("Expected RLE %d: %s, got %s\n", i, expected[i], rle)
   477  		}
   478  	}
   479  }
   480  
   481  func TestBlockMerge(t *testing.T) {
   482  	numVoxels := 64 * 64 * 64
   483  	testvol := make([]uint64, numVoxels)
   484  	labels := make([]uint64, 5)
   485  	mergeSet := make(Set, 3)
   486  	for i := 0; i < 5; i++ {
   487  		var newlabel uint64
   488  		for {
   489  			newlabel = uint64(rand.Int63())
   490  			ok := true
   491  			for j := 0; j < i; j++ {
   492  				if newlabel == labels[j] {
   493  					ok = false
   494  				}
   495  			}
   496  			if ok {
   497  				break
   498  			}
   499  		}
   500  		labels[i] = newlabel
   501  		if i > 1 {
   502  			mergeSet[labels[i]] = struct{}{}
   503  		}
   504  	}
   505  	for i := 0; i < numVoxels; i++ {
   506  		testvol[i] = labels[i%5]
   507  	}
   508  	block, err := MakeBlock(dvid.AliasUint64ToByte(testvol), dvid.Point3d{64, 64, 64})
   509  	if err != nil {
   510  		t.Fatalf("error making block: %v\n", err)
   511  	}
   512  	runtime.KeepAlive(&testvol)
   513  	op := MergeOp{
   514  		Target: labels[0],
   515  		Merged: mergeSet,
   516  	}
   517  	mergedBlock, err := block.MergeLabels(op)
   518  	if err != nil {
   519  		t.Fatalf("error merging block: %v\n", err)
   520  	}
   521  	volbytes, size := mergedBlock.MakeLabelVolume()
   522  	if size[0] != 64 || size[1] != 64 || size[2] != 64 {
   523  		t.Fatalf("bad merged block size returned: %s\n", size)
   524  	}
   525  	uint64arr, err := dvid.AliasByteToUint64(volbytes)
   526  	if err != nil {
   527  		t.Fatalf("error converting label byte array: %v\n", err)
   528  	}
   529  	for i := 0; i < numVoxels; i++ {
   530  		curlabel := uint64arr[i]
   531  		_, wasMerged := mergeSet[curlabel]
   532  		if wasMerged {
   533  			t.Fatalf("found voxel %d had label %d when it %s merged -> %d\n", i, curlabel, mergeSet, labels[0])
   534  		} else if curlabel != labels[0] && curlabel != labels[1] {
   535  			t.Fatalf("found voxel %d had label %d which is not expected labels %d or %d\n", i, curlabel, labels[0], labels[1])
   536  		}
   537  	}
   538  	runtime.KeepAlive(&volbytes)
   539  }
   540  
   541  func TestBlockReplaceLabel(t *testing.T) {
   542  	numVoxels := 64 * 64 * 64
   543  	testvol := make([]uint64, numVoxels)
   544  	for i := 0; i < numVoxels; i++ {
   545  		testvol[i] = 4
   546  	}
   547  	block, err := MakeBlock(dvid.AliasUint64ToByte(testvol), dvid.Point3d{64, 64, 64})
   548  	if err != nil {
   549  		t.Fatalf("error making block: %v\n", err)
   550  	}
   551  	runtime.KeepAlive(&testvol)
   552  	_, replaceSize, err := block.ReplaceLabel(2, 1)
   553  	if err != nil {
   554  		t.Fatalf("error replacing block: %v\n", err)
   555  	}
   556  	if replaceSize != 0 {
   557  		t.Errorf("expected replaced # voxels to be zero, got %d\n", replaceSize)
   558  	}
   559  	tmpblock, replaceSize, err := block.ReplaceLabel(4, 1)
   560  	if err != nil {
   561  		t.Fatalf("error replacing block: %v\n", err)
   562  	}
   563  	if replaceSize != uint64(numVoxels) {
   564  		t.Errorf("expected replaced # voxels to be %d, got %d\n", numVoxels, replaceSize)
   565  	}
   566  	volbytes, size := tmpblock.MakeLabelVolume()
   567  	if size[0] != 64 || size[1] != 64 || size[2] != 64 {
   568  		t.Fatalf("bad replaced block size returned: %s\n", size)
   569  	}
   570  	uint64arr, err := dvid.AliasByteToUint64(volbytes)
   571  	if err != nil {
   572  		t.Fatalf("error converting label byte array: %v\n", err)
   573  	}
   574  	for i, label := range uint64arr {
   575  		if label != 1 {
   576  			t.Errorf("expected label 1 after replacement in voxel %d, got %d\n", i, label)
   577  			break
   578  		}
   579  	}
   580  
   581  	labels := make([]uint64, 5)
   582  	for i := 0; i < 5; i++ {
   583  		var newlabel uint64
   584  		for {
   585  			newlabel = uint64(rand.Int63())
   586  			ok := true
   587  			for j := 0; j < i; j++ {
   588  				if newlabel == labels[j] {
   589  					ok = false
   590  				}
   591  			}
   592  			if ok {
   593  				break
   594  			}
   595  		}
   596  		labels[i] = newlabel
   597  	}
   598  	for i := 0; i < numVoxels; i++ {
   599  		testvol[i] = labels[i%4]
   600  	}
   601  	block, err = MakeBlock(dvid.AliasUint64ToByte(testvol), dvid.Point3d{64, 64, 64})
   602  	if err != nil {
   603  		t.Fatalf("error making block: %v\n", err)
   604  	}
   605  	runtime.KeepAlive(&testvol)
   606  	tmpblock, replaceSize, err = block.ReplaceLabel(labels[0], labels[4])
   607  	if err != nil {
   608  		t.Fatalf("error merging block: %v\n", err)
   609  	}
   610  	if replaceSize != uint64(numVoxels/4) {
   611  		t.Errorf("expected replaced # voxels with %d = %d, got %d\n", labels[0], numVoxels/4, replaceSize)
   612  	}
   613  	replacedBlock, replaceSize, err := tmpblock.ReplaceLabel(labels[1], labels[2])
   614  	if err != nil {
   615  		t.Fatalf("error merging block: %v\n", err)
   616  	}
   617  	volbytes, size = replacedBlock.MakeLabelVolume()
   618  	if size[0] != 64 || size[1] != 64 || size[2] != 64 {
   619  		t.Fatalf("bad replaced block size returned: %s\n", size)
   620  	}
   621  	uint64arr, err = dvid.AliasByteToUint64(volbytes)
   622  	if err != nil {
   623  		t.Fatalf("error converting label byte array: %v\n", err)
   624  	}
   625  	for i := 0; i < numVoxels; i++ {
   626  		switch uint64arr[i] {
   627  		case labels[0]:
   628  			t.Fatalf("bad label at voxel %d: %d, should have been replaced by label %d\n", i, uint64arr[i], labels[4])
   629  		case labels[1]:
   630  			t.Fatalf("bad label at voxel %d: %d, should have been replaced by label %d\n", i, uint64arr[i], labels[2])
   631  		case labels[2], labels[3], labels[4]:
   632  			// good
   633  		default:
   634  			t.Fatalf("bad label at voxel %d: %d, not in expected labels %v\n", i, uint64arr[i], labels)
   635  		}
   636  	}
   637  	runtime.KeepAlive(&volbytes)
   638  }
   639  
   640  func TestBlockReplaceLabels(t *testing.T) {
   641  	numVoxels := 64 * 64 * 64
   642  	testvol := make([]uint64, numVoxels)
   643  	for i := 0; i < numVoxels; i++ {
   644  		testvol[i] = uint64(i) % 4
   645  	}
   646  	block, err := MakeBlock(dvid.AliasUint64ToByte(testvol), dvid.Point3d{64, 64, 64})
   647  	if err != nil {
   648  		t.Fatalf("error making block: %v\n", err)
   649  	}
   650  	runtime.KeepAlive(&testvol)
   651  	mapping := map[uint64]uint64{
   652  		0: 5,
   653  		1: 6,
   654  		2: 7,
   655  		3: 8,
   656  	}
   657  	replaceBlock, replaced, err := block.ReplaceLabels(mapping)
   658  	if err != nil {
   659  		t.Fatalf("error replacing block: %v\n", err)
   660  	}
   661  	if !replaced {
   662  		t.Errorf("expected replacement and got none\n")
   663  	}
   664  	volbytes, size := replaceBlock.MakeLabelVolume()
   665  	if size[0] != 64 || size[1] != 64 || size[2] != 64 {
   666  		t.Fatalf("bad replaced block size returned: %s\n", size)
   667  	}
   668  	uint64arr, err := dvid.AliasByteToUint64(volbytes)
   669  	if err != nil {
   670  		t.Fatalf("error converting label byte array: %v\n", err)
   671  	}
   672  	for i, label := range uint64arr {
   673  		if label != uint64(i%4)+5 {
   674  			t.Errorf("expected label %d after replacement in voxel %d, got %d\n", (i%4)+5, i, label)
   675  			break
   676  		}
   677  	}
   678  	runtime.KeepAlive(&volbytes)
   679  }
   680  
   681  func TestBlockSplitAndRLEs(t *testing.T) {
   682  	numVoxels := 32 * 32 * 32
   683  	testvol := make([]uint64, numVoxels)
   684  	for i := 0; i < numVoxels; i++ {
   685  		testvol[i] = uint64(i)
   686  	}
   687  	label := uint64(numVoxels * 10) // > previous labels
   688  	for x := 11; x < 31; x++ {
   689  		setLabel(testvol, 32, x, 8, 16, label)
   690  	}
   691  	block, err := MakeBlock(dvid.AliasUint64ToByte(testvol), dvid.Point3d{32, 32, 32})
   692  	if err != nil {
   693  		t.Fatalf("error making block: %v\n", err)
   694  	}
   695  	runtime.KeepAlive(&testvol)
   696  
   697  	splitRLEs := dvid.RLEs{
   698  		dvid.NewRLE(dvid.Point3d{81, 40, 80}, 6),
   699  		dvid.NewRLE(dvid.Point3d{90, 40, 80}, 3),
   700  	}
   701  	op := SplitOp{NewLabel: label + 1, Target: label, RLEs: splitRLEs}
   702  	pb := PositionedBlock{
   703  		Block:  *block,
   704  		BCoord: dvid.ChunkPoint3d{2, 1, 2}.ToIZYXString(),
   705  	}
   706  	split, keptSize, splitSize, err := pb.Split(op)
   707  	if err != nil {
   708  		t.Fatalf("error doing split: %v\n", err)
   709  	}
   710  	if keptSize != 11 {
   711  		t.Errorf("Expected kept size of 11, got %d\n", keptSize)
   712  	}
   713  	if splitSize != 9 {
   714  		t.Errorf("Expected split size of 9, got %d\n", splitSize)
   715  	}
   716  
   717  	var buf bytes.Buffer
   718  	lbls := Set{}
   719  	lbls[label] = struct{}{}
   720  	outOp := NewOutputOp(&buf)
   721  	go WriteRLEs(lbls, outOp, dvid.Bounds{})
   722  	pb = PositionedBlock{
   723  		Block:  *split,
   724  		BCoord: dvid.ChunkPoint3d{2, 1, 2}.ToIZYXString(),
   725  	}
   726  	outOp.Process(&pb)
   727  	if err = outOp.Finish(); err != nil {
   728  		t.Fatalf("error writing RLEs: %v\n", err)
   729  	}
   730  	output, err := ioutil.ReadAll(&buf)
   731  	if err != nil {
   732  		t.Fatalf("error on reading WriteRLEs: %v\n", err)
   733  	}
   734  	if len(output) != 3*16 {
   735  		t.Fatalf("expected 3 RLEs (48 bytes), got %d bytes\n", len(output))
   736  	}
   737  	var rles dvid.RLEs
   738  	if err = rles.UnmarshalBinary(output); err != nil {
   739  		t.Fatalf("unable to parse binary RLEs: %v\n", err)
   740  	}
   741  	expected := dvid.RLEs{
   742  		dvid.NewRLE(dvid.Point3d{75, 40, 80}, 6),
   743  		dvid.NewRLE(dvid.Point3d{87, 40, 80}, 3),
   744  		dvid.NewRLE(dvid.Point3d{93, 40, 80}, 2),
   745  	}
   746  	for i, rle := range rles {
   747  		if rle != expected[i] {
   748  			t.Errorf("Expected RLE %d: %s, got %s\n", i, expected[i], rle)
   749  		}
   750  	}
   751  }
   752  
   753  func TestSolidBlockSize(t *testing.T) {
   754  	testLabel := uint64(9174832)
   755  	numVoxels := 64 * 64 * 64
   756  	blockVol := make([]uint64, numVoxels)
   757  	for i := 0; i < numVoxels; i++ {
   758  		blockVol[i] = testLabel
   759  	}
   760  	block, err := MakeBlock(dvid.AliasUint64ToByte(blockVol), dvid.Point3d{64, 64, 64})
   761  	if err != nil {
   762  		t.Fatalf("error making block 0: %v\n", err)
   763  	}
   764  	runtime.KeepAlive(&blockVol)
   765  	compressed, err := block.MarshalBinary()
   766  	if err != nil {
   767  		t.Fatal(err)
   768  	}
   769  	if len(compressed) > 24 {
   770  		t.Errorf("solid block had %d bytes instead of optimal 24 bytes\n", len(compressed))
   771  	}
   772  	solidBlock := MakeSolidBlock(testLabel, dvid.Point3d{64, 64, 64})
   773  	uint64array, size := solidBlock.MakeLabelVolume()
   774  	if size[0] != 64 || size[1] != 64 || size[2] != 64 {
   775  		t.Fatalf("solid block didn't return appropriate size: %v\n", size)
   776  	}
   777  	uint64array2, size2 := block.MakeLabelVolume()
   778  	if size2[0] != 64 || size2[1] != 64 || size2[2] != 64 {
   779  		t.Fatalf("one label block didn't return appropriate size: %v\n", size2)
   780  	}
   781  	if !bytes.Equal(uint64array, uint64array2) {
   782  		t.Fatalf("solid block path does not equal single label encoded path\n")
   783  	}
   784  	labelVol, err := dvid.AliasByteToUint64(uint64array)
   785  	if err != nil {
   786  		t.Fatal(err)
   787  	}
   788  	for i := 0; i < numVoxels; i++ {
   789  		if labelVol[i] != testLabel {
   790  			t.Fatalf("uncompressed label volume had label %d instead of expected label %d @ position %d\n", labelVol[i], testLabel, i)
   791  		}
   792  	}
   793  	runtime.KeepAlive(&uint64array)
   794  }
   795  
   796  func TestBinaryBlocks(t *testing.T) {
   797  	numVoxels := 64 * 64 * 64
   798  	blockVol0 := make([]uint64, numVoxels)
   799  	blockVol1 := make([]uint64, numVoxels)
   800  
   801  	background := uint64(1000)
   802  	target := uint64(7)
   803  	var i, x, y, z int32
   804  	for z = 0; z < 64; z++ {
   805  		for y = 0; y < 64; y++ {
   806  			for x = 0; x < 64; x++ {
   807  				if x >= 23 && x <= 34 && y >= 37 && y <= 50 {
   808  					blockVol0[i] = target
   809  				} else {
   810  					blockVol0[i] = background
   811  				}
   812  				i++
   813  			}
   814  		}
   815  	}
   816  	i = 0
   817  	for z = 0; z < 64; z++ {
   818  		for y = 0; y < 64; y++ {
   819  			for x = 0; x < 64; x++ {
   820  				if x >= 26 && x <= 31 && y >= 39 && y <= 45 {
   821  					blockVol1[i] = target
   822  				} else {
   823  					blockVol1[i] = background
   824  				}
   825  				i++
   826  			}
   827  		}
   828  	}
   829  
   830  	block0, err := MakeBlock(dvid.AliasUint64ToByte(blockVol0), dvid.Point3d{64, 64, 64})
   831  	if err != nil {
   832  		t.Fatalf("error making block 0: %v\n", err)
   833  	}
   834  	runtime.KeepAlive(&blockVol0)
   835  	block1, err := MakeBlock(dvid.AliasUint64ToByte(blockVol1), dvid.Point3d{64, 64, 64})
   836  	if err != nil {
   837  		t.Fatalf("error making block 0: %v\n", err)
   838  	}
   839  	runtime.KeepAlive(&blockVol1)
   840  
   841  	pb0 := PositionedBlock{
   842  		Block:  *block0,
   843  		BCoord: dvid.ChunkPoint3d{1, 1, 1}.ToIZYXString(),
   844  	}
   845  	pb1 := PositionedBlock{
   846  		Block:  *block1,
   847  		BCoord: dvid.ChunkPoint3d{1, 1, 2}.ToIZYXString(),
   848  	}
   849  
   850  	var buf bytes.Buffer
   851  	lbls := Set{}
   852  	lbls[target] = struct{}{}
   853  	outOp := NewOutputOp(&buf)
   854  	go WriteBinaryBlocks(target, lbls, outOp, dvid.Bounds{})
   855  	outOp.Process(&pb0)
   856  	outOp.Process(&pb1)
   857  	if err = outOp.Finish(); err != nil {
   858  		t.Fatalf("error writing binary blocks: %v\n", err)
   859  	}
   860  	got, err := ReceiveBinaryBlocks(&buf)
   861  	if err != nil {
   862  		t.Fatalf("error on reading binary blocks: %v\n", err)
   863  	}
   864  	if len(got) != 2 {
   865  		t.Fatalf("expected 2 binary blocks got %d\n", len(got))
   866  	}
   867  	if got[0].Label != target {
   868  		t.Errorf("expected label %d for binary block 0, got %s\n", target, got[0])
   869  	}
   870  	if got[1].Label != target {
   871  		t.Errorf("expected label %d for binary block 1, got %s\n", target, got[0])
   872  	}
   873  	i = 0
   874  	for z = 0; z < 64; z++ {
   875  		for y = 0; y < 64; y++ {
   876  			for x = 0; x < 64; x++ {
   877  				if x >= 23 && x <= 34 && y >= 37 && y <= 50 {
   878  					if !got[0].Voxels[i] {
   879  						t.Fatalf("error in binary block 0: bad unset bit @ (%d,%d,%d)\n", x, y, z)
   880  					}
   881  				} else {
   882  					if got[0].Voxels[i] {
   883  						t.Fatalf("error in binary block 0: bad set bit @ (%d,%d,%d)\n", x, y, z)
   884  					}
   885  				}
   886  				i++
   887  			}
   888  		}
   889  	}
   890  	i = 0
   891  	for z = 0; z < 64; z++ {
   892  		for y = 0; y < 64; y++ {
   893  			for x = 0; x < 64; x++ {
   894  				if x >= 26 && x <= 31 && y >= 39 && y <= 45 {
   895  					if !got[1].Voxels[i] {
   896  						t.Errorf("error in binary block 1: bad unset bit @ (%d,%d,%d)\n", x, y, z)
   897  					}
   898  				} else {
   899  					if got[1].Voxels[i] {
   900  						t.Errorf("error in binary block 1: bad set bit @ (%d,%d,%d)\n", x, y, z)
   901  					}
   902  				}
   903  				i++
   904  			}
   905  		}
   906  	}
   907  }
   908  
   909  func testBlockPointLabels(t *testing.T, block *Block) {
   910  	labelData, _ := block.MakeLabelVolume()
   911  	pts := make([]dvid.Point3d, 5)
   912  	for n := 0; n < 1000; n++ {
   913  		for m := 0; m < 5; m++ {
   914  			pts[m] = dvid.Point3d{
   915  				int32(rand.Int() % 64),
   916  				int32(rand.Int() % 64),
   917  				int32(rand.Int() % 64),
   918  			}
   919  		}
   920  		labels := block.GetPointLabels(pts)
   921  		for m, pt := range pts {
   922  			i := (pt[2]*64*64 + pt[1]*64 + pt[0]) * 8
   923  			label := binary.LittleEndian.Uint64(labelData[i : i+8])
   924  			if label != labels[m] {
   925  				t.Fatalf("For pt %s expected label %d got label %d\n", pt, label, labels[m])
   926  			}
   927  		}
   928  	}
   929  }
   930  
   931  func TestPointLabels(t *testing.T) {
   932  	var d testData
   933  	var block *Block
   934  	var err error
   935  	for _, filename := range testFiles {
   936  		d, err = loadData(filename)
   937  		if err != nil {
   938  			t.Fatal(err)
   939  		}
   940  		block, err = MakeBlock(d.b, dvid.Point3d{64, 64, 64})
   941  		if err != nil {
   942  			t.Fatal(err)
   943  		}
   944  		testBlockPointLabels(t, block)
   945  	}
   946  	testBlockPointLabels(t, MakeSolidBlock(23, dvid.Point3d{64, 64, 64}))
   947  }
   948  
   949  func BenchmarkGoogleCompress(b *testing.B) {
   950  	d := make([]testData, len(testFiles))
   951  	for i, filename := range testFiles {
   952  		var err error
   953  		d[i], err = loadData(filename)
   954  		if err != nil {
   955  			b.Fatal(err)
   956  		}
   957  	}
   958  	b.ResetTimer()
   959  	for i := 0; i < b.N; i++ {
   960  		_, err := oldCompressUint64(d[i%len(d)].u, dvid.Point3d{64, 64, 64})
   961  		if err != nil {
   962  			b.Fatal(err)
   963  		}
   964  	}
   965  }
   966  
   967  func BenchmarkDvidCompress(b *testing.B) {
   968  	d := make([]testData, len(testFiles))
   969  	for i, filename := range testFiles {
   970  		var err error
   971  		d[i], err = loadData(filename)
   972  		if err != nil {
   973  			b.Fatal(err)
   974  		}
   975  	}
   976  	b.ResetTimer()
   977  	for i := 0; i < b.N; i++ {
   978  		_, err := MakeBlock(d[i%len(d)].b, dvid.Point3d{64, 64, 64})
   979  		if err != nil {
   980  			b.Fatal(err)
   981  		}
   982  	}
   983  }
   984  
   985  func BenchmarkDvidCompressGzip(b *testing.B) {
   986  	d := make([]testData, len(testFiles))
   987  	for i, filename := range testFiles {
   988  		var err error
   989  		d[i], err = loadData(filename)
   990  		if err != nil {
   991  			b.Fatal(err)
   992  		}
   993  	}
   994  	b.ResetTimer()
   995  	for i := 0; i < b.N; i++ {
   996  		block, err := MakeBlock(d[i%len(d)].b, dvid.Point3d{64, 64, 64})
   997  		if err != nil {
   998  			b.Fatal(err)
   999  		}
  1000  		var gzipOut bytes.Buffer
  1001  		zw := gzip.NewWriter(&gzipOut)
  1002  		if _, err = zw.Write(block.data); err != nil {
  1003  			b.Fatal(err)
  1004  		}
  1005  		zw.Flush()
  1006  	}
  1007  }
  1008  
  1009  func BenchmarkDvidCompressLZ4(b *testing.B) {
  1010  	d := make([]testData, len(testFiles))
  1011  	for i, filename := range testFiles {
  1012  		var err error
  1013  		d[i], err = loadData(filename)
  1014  		if err != nil {
  1015  			b.Fatal(err)
  1016  		}
  1017  	}
  1018  	b.ResetTimer()
  1019  	for i := 0; i < b.N; i++ {
  1020  		block, err := MakeBlock(d[i%len(d)].b, dvid.Point3d{64, 64, 64})
  1021  		if err != nil {
  1022  			b.Fatal(err)
  1023  		}
  1024  		var n int
  1025  		dvidLZ4 := make([]byte, lz4.CompressBound(block.data))
  1026  		if n, err = lz4.Compress(block.data, dvidLZ4); err != nil {
  1027  			b.Fatal(err)
  1028  		}
  1029  		dvidLZ4 = dvidLZ4[:n]
  1030  	}
  1031  }
  1032  
  1033  func BenchmarkDvidMarshalGzip(b *testing.B) {
  1034  	var block [4]*Block
  1035  	for i, filename := range testFiles {
  1036  		d, err := loadData(filename)
  1037  		if err != nil {
  1038  			b.Fatal(err)
  1039  		}
  1040  		block[i%4], err = MakeBlock(d.b, dvid.Point3d{64, 64, 64})
  1041  		if err != nil {
  1042  			b.Fatal(err)
  1043  		}
  1044  	}
  1045  	b.ResetTimer()
  1046  	var totbytes int
  1047  	for i := 0; i < b.N; i++ {
  1048  		var gzipOut bytes.Buffer
  1049  		zw := gzip.NewWriter(&gzipOut)
  1050  		if _, err := zw.Write(block[i%4].data); err != nil {
  1051  			b.Fatal(err)
  1052  		}
  1053  		zw.Flush()
  1054  		zw.Close()
  1055  		compressed := gzipOut.Bytes()
  1056  		totbytes += len(compressed)
  1057  	}
  1058  }
  1059  
  1060  func BenchmarkDvidUnmarshalGzip(b *testing.B) {
  1061  	var compressed [4][]byte
  1062  	for i, filename := range testFiles {
  1063  		d, err := loadData(filename)
  1064  		if err != nil {
  1065  			b.Fatal(err)
  1066  		}
  1067  		block, err := MakeBlock(d.b, dvid.Point3d{64, 64, 64})
  1068  		if err != nil {
  1069  			b.Fatal(err)
  1070  		}
  1071  		var gzipOut bytes.Buffer
  1072  		zw := gzip.NewWriter(&gzipOut)
  1073  		if _, err = zw.Write(block.data); err != nil {
  1074  			b.Fatal(err)
  1075  		}
  1076  		zw.Flush()
  1077  		zw.Close()
  1078  		compressed[i%4] = make([]byte, gzipOut.Len())
  1079  		copy(compressed[i%4], gzipOut.Bytes())
  1080  	}
  1081  	b.ResetTimer()
  1082  	for i := 0; i < b.N; i++ {
  1083  		gzipIn := bytes.NewBuffer(compressed[i%4])
  1084  		zr, err := gzip.NewReader(gzipIn)
  1085  		if err != nil {
  1086  			b.Fatal(err)
  1087  		}
  1088  		data, err := ioutil.ReadAll(zr)
  1089  		if err != nil {
  1090  			b.Fatal(err)
  1091  		}
  1092  		var block Block
  1093  		if err := block.UnmarshalBinary(data); err != nil {
  1094  			b.Fatal(err)
  1095  		}
  1096  		zr.Close()
  1097  	}
  1098  }
  1099  
  1100  func BenchmarkDvidMarshalLZ4(b *testing.B) {
  1101  	var block [4]*Block
  1102  	for i, filename := range testFiles {
  1103  		d, err := loadData(filename)
  1104  		if err != nil {
  1105  			b.Fatal(err)
  1106  		}
  1107  		block[i%4], err = MakeBlock(d.b, dvid.Point3d{64, 64, 64})
  1108  		if err != nil {
  1109  			b.Fatal(err)
  1110  		}
  1111  	}
  1112  	b.ResetTimer()
  1113  	var totbytes int
  1114  	for i := 0; i < b.N; i++ {
  1115  		data := make([]byte, lz4.CompressBound(block[i%4].data))
  1116  		var outsize int
  1117  		var err error
  1118  		if outsize, err = lz4.Compress(block[i%4].data, data); err != nil {
  1119  			b.Fatal(err)
  1120  		}
  1121  		compressed := data[:outsize]
  1122  		totbytes += len(compressed)
  1123  	}
  1124  }
  1125  
  1126  func BenchmarkDvidUnmarshalLZ4(b *testing.B) {
  1127  	var origsize [4]int
  1128  	var compressed [4][]byte
  1129  	for i, filename := range testFiles {
  1130  		d, err := loadData(filename)
  1131  		if err != nil {
  1132  			b.Fatal(err)
  1133  		}
  1134  		block, err := MakeBlock(d.b, dvid.Point3d{64, 64, 64})
  1135  		if err != nil {
  1136  			b.Fatal(err)
  1137  		}
  1138  		data := make([]byte, lz4.CompressBound(block.data))
  1139  		var outsize int
  1140  		if outsize, err = lz4.Compress(block.data, data); err != nil {
  1141  			b.Fatal(err)
  1142  		}
  1143  		compressed[i%4] = data[:outsize]
  1144  		origsize[i%4] = len(block.data)
  1145  	}
  1146  	b.ResetTimer()
  1147  	for i := 0; i < b.N; i++ {
  1148  		data := make([]byte, origsize[i%4])
  1149  		if err := lz4.Uncompress(compressed[i%4], data); err != nil {
  1150  			b.Fatal(err)
  1151  		}
  1152  		var block Block
  1153  		if err := block.UnmarshalBinary(data); err != nil {
  1154  			b.Fatal(err)
  1155  		}
  1156  	}
  1157  }
  1158  
  1159  func BenchmarkGoogleReturnArray(b *testing.B) {
  1160  	var compressed [4][]uint32
  1161  	for i, filename := range testFiles {
  1162  		d, err := loadData(filename)
  1163  		if err != nil {
  1164  			b.Fatal(err)
  1165  		}
  1166  		compressed[i%4], err = oldCompressUint64(d.u, dvid.Point3d{64, 64, 64})
  1167  		if err != nil {
  1168  			b.Fatal(err)
  1169  		}
  1170  	}
  1171  	b.ResetTimer()
  1172  	for i := 0; i < b.N; i++ {
  1173  		_, err := oldDecompressUint64(compressed[i%4], dvid.Point3d{64, 64, 64})
  1174  		if err != nil {
  1175  			b.Fatal(err)
  1176  		}
  1177  	}
  1178  }
  1179  
  1180  func BenchmarkDvidReturnArray(b *testing.B) {
  1181  	var block [4]*Block
  1182  	for i, filename := range testFiles {
  1183  		d, err := loadData(filename)
  1184  		if err != nil {
  1185  			b.Fatal(err)
  1186  		}
  1187  		block[i%4], err = MakeBlock(d.b, dvid.Point3d{64, 64, 64})
  1188  		if err != nil {
  1189  			b.Fatal(err)
  1190  		}
  1191  	}
  1192  	b.ResetTimer()
  1193  	for i := 0; i < b.N; i++ {
  1194  		labelarray, size := block[i%4].MakeLabelVolume()
  1195  		if int64(len(labelarray)) != size.Prod()*8 {
  1196  			b.Fatalf("expected label volume returned is %d bytes, got %d instead\n", size.Prod()*8, len(labelarray))
  1197  		}
  1198  	}
  1199  }
  1200  
  1201  func BenchmarkPointLabels(b *testing.B) {
  1202  	var d testData
  1203  	numFiles := len(testFiles)
  1204  	blocks := make([]*Block, numFiles)
  1205  	var err error
  1206  	for i, filename := range testFiles {
  1207  		d, err = loadData(filename)
  1208  		if err != nil {
  1209  			b.Fatal(err)
  1210  		}
  1211  		blocks[i], err = MakeBlock(d.b, dvid.Point3d{64, 64, 64})
  1212  		if err != nil {
  1213  			b.Fatal(err)
  1214  		}
  1215  	}
  1216  	b.ResetTimer()
  1217  	var x, y, z int32
  1218  	for i := 0; i < b.N; i++ {
  1219  		x = int32(i) % 64
  1220  		y = (x + 8) % 64
  1221  		z = (y + 8) % 64
  1222  		pts := []dvid.Point3d{
  1223  			dvid.Point3d{x, y, z},
  1224  			dvid.Point3d{y, x, z},
  1225  			dvid.Point3d{z, x, y},
  1226  		}
  1227  		for f := 0; f < numFiles; f++ {
  1228  			_ = blocks[f].GetPointLabels(pts)
  1229  		}
  1230  	}
  1231  }
  1232  
  1233  func BenchmarkOldPointLabels(b *testing.B) {
  1234  	var d testData
  1235  	numFiles := len(testFiles)
  1236  	blocks := make([]*Block, numFiles)
  1237  	var err error
  1238  	for i, filename := range testFiles {
  1239  		d, err = loadData(filename)
  1240  		if err != nil {
  1241  			b.Fatal(err)
  1242  		}
  1243  		blocks[i], err = MakeBlock(d.b, dvid.Point3d{64, 64, 64})
  1244  		if err != nil {
  1245  			b.Fatal(err)
  1246  		}
  1247  	}
  1248  	b.ResetTimer()
  1249  	var x, y, z int32
  1250  	for i := 0; i < b.N; i++ {
  1251  		x = int32(i) % 64
  1252  		y = (x + 8) % 64
  1253  		z = (y + 8) % 64
  1254  		pts := []dvid.Point3d{
  1255  			dvid.Point3d{x, y, z},
  1256  			dvid.Point3d{y, x, z},
  1257  			dvid.Point3d{z, x, y},
  1258  		}
  1259  		for f := 0; f < numFiles; f++ {
  1260  			labelData, _ := blocks[f].MakeLabelVolume()
  1261  			for _, pt := range pts {
  1262  				i := (pt[2]*64*64 + pt[1]*64 + pt[0]) * 8
  1263  				_ = binary.LittleEndian.Uint64(labelData[i : i+8])
  1264  			}
  1265  		}
  1266  	}
  1267  }