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
}
func Aggregate(goroutines []*Goroutine, similar Similarity) []*Bucket {
	type count struct {
		ids   []int
		first bool
	}
	b := map[*Signature]*count{}
	
	for _, routine := range goroutines {
		found := false
		for key, c := range b {
			
			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) {
					
					
					newKey := key.merge(&routine.Signature)
					b[newKey] = c
					delete(b, key)
				}
				break
			}
		}
		if !found {
			
			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
}
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 }
// Aggregate merges similar goroutines into buckets.
//
// The buckets are ordered in library provided order of relevancy. You can
// reorder at your chosing.
Aggregate merges similar goroutines into buckets . The buckets are ordered in library provided order of relevancy . You can reorder at your chosing .