code: func Aggregate(goroutines []*Goroutine, similar Similarity) []*Bucket {
  	type count struct {
  		ids   []int
  		first bool
  	}
  	b := map[*Signature]*count{}
  	// O(n²). Fix eventually.
  	for _, routine := range goroutines {
  		found := false
  		for key, c := range b {
  			// When a match is found, this effectively drops the other goroutine ID.
  			if key.similar(&routine.Signature, similar) {
  				found = true
  				c.ids = append(c.ids, routine.ID)
  				c.first = c.first || routine.First
  				if !key.equal(&routine.Signature) {
  					// Almost but not quite equal. There's different pointers passed
  					// around but the same values. Zap out the different values.
  					newKey := key.merge(&routine.Signature)
  					b[newKey] = c
  					delete(b, key)
  				}
  				break
  			}
  		}
  		if !found {
  			// Create a copy of the Signature, since it will be mutated.
  			key := &Signature{}
  			*key = routine.Signature
  			b[key] = &count{ids: []int{routine.ID}, first: routine.First}
  		}
  	}
  	out := make(buckets, 0, len(b))
  	for signature, c := range b {
  		sort.Ints(c.ids)
  		out = append(out, &Bucket{Signature: *signature, IDs: c.ids, First: c.first})
  	}
  	sort.Sort(out)
  	return out
  }
docs: // Aggregate merges similar goroutines into buckets.
  //
  // The buckets are ordered in library provided order of relevancy. You can
  // reorder at your chosing.