packfile: parallelize deltification of objects in groups

Signed-off-by: Miguel Molina <miguel@erizocosmi.co>
diff --git a/plumbing/format/packfile/delta_selector.go b/plumbing/format/packfile/delta_selector.go
index 021b520..0b3539d 100644
--- a/plumbing/format/packfile/delta_selector.go
+++ b/plumbing/format/packfile/delta_selector.go
@@ -2,6 +2,7 @@
 
 import (
 	"sort"
+	"sync"
 
 	"gopkg.in/src-d/go-git.v4/plumbing"
 	"gopkg.in/src-d/go-git.v4/plumbing/storer"
@@ -40,7 +41,36 @@
 
 	dw.sort(otp)
 
-	if err := dw.walk(otp); err != nil {
+	var objectGroups [][]*ObjectToPack
+	var prev *ObjectToPack
+	i := -1
+	for _, obj := range otp {
+		if prev == nil || prev.Type() != obj.Type() {
+			objectGroups = append(objectGroups, []*ObjectToPack{obj})
+			i++
+			prev = obj
+		} else {
+			objectGroups[i] = append(objectGroups[i], obj)
+		}
+	}
+
+	var wg sync.WaitGroup
+	var once sync.Once
+	for _, objs := range objectGroups {
+		objs := objs
+		wg.Add(1)
+		go func() {
+			if walkErr := dw.walk(objs); walkErr != nil {
+				once.Do(func() {
+					err = walkErr
+				})
+			}
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+
+	if err != nil {
 		return nil, err
 	}
 
diff --git a/plumbing/format/packfile/diff_delta.go b/plumbing/format/packfile/diff_delta.go
index 7c9360e..2e58ec6 100644
--- a/plumbing/format/packfile/diff_delta.go
+++ b/plumbing/format/packfile/diff_delta.go
@@ -135,26 +135,6 @@
 	ibuf.Reset()
 }
 
-// https://lemire.me/blog/2015/10/22/faster-hashing-without-effort/
-func hashBuf(buf []byte) int64 {
-	var h int64
-	var i int
-	len := len(buf)
-	for ; i+3 < len; i += 4 {
-		h = 31*31*31*31*h +
-			31*31*31*int64(buf[i]) +
-			31*31*int64(buf[i+1]) +
-			31*int64(buf[i+2]) +
-			int64(buf[i+3])
-	}
-
-	for ; i < len; i++ {
-		h = 31*h + int64(buf[i])
-	}
-
-	return h
-}
-
 func matchLength(src, tgt []byte, otgt, osrc int) int {
 	l := 0
 	for {