Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perfomance: increase performance by map usage #411

Merged
merged 1 commit into from
Sep 1, 2022
Merged

perfomance: increase performance by map usage #411

merged 1 commit into from
Sep 1, 2022

Conversation

pnsafonov
Copy link

Perfomance fix

@wader
Copy link
Owner

wader commented Sep 1, 2022

Thanks and thanks for profiling and looking into this 👍

One future improvement related to memory usage would be to use a *map[string]struct{} instead which i think would save some bytes (a pointer vs a pointer, length and capacity it think?) but the indirection would cost some performance. We can experiment with that later.

@wader wader merged commit 16ebdc1 into wader:master Sep 1, 2022
@wader
Copy link
Owner

wader commented Sep 1, 2022

Will probably do an additional PR soon if it makes sense to change it into a map[string]*Value so it can also be used by interp/decode.StructDecodeValue JQValueKey(name string) any

@pnsafonov
Copy link
Author

Thanks and thanks for profiling and looking into this +1

One future improvement related to memory usage would be to use a *map[string]struct{} instead which i think would save some bytes (a pointer vs a pointer, length and capacity it think?) but the indirection would cost some performance. We can experiment with that later.

Change map[string]*Value to *map[string]*Value will not save any byte. map is implemented via pointer.

It can be checked by:

package main

import (
	"fmt"
	"unsafe"
)

// 8
type DataA struct {
	keys map[string]struct{} // ptr to map
}

// 8
type DataB struct {
	keys *map[string]struct{} // ptr to ptr
}

// 12
type DataC struct {
	id1 int32
	id2 int32
	id3 int32
}

// 24
type DataD struct {
	values []int // ptr to array, len, cap
}

// 8
type DataE struct {
	values *[]int // ptr to ptr (ptr to array, len, cap)
}

func main() {
	d1 := DataA{
		keys: make(map[string]struct{}),
	}
	m2 := make(map[string]struct{})
	d2 := DataB{
		keys: &m2,
	}
	d3 := DataC{}
	d4 := DataD{
		values: []int{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
	}
	sl5 := []int{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
	d5 := DataE{
		values: &sl5,
	}

	s1 := unsafe.Sizeof(d1)
	s2 := unsafe.Sizeof(d2)
	s3 := unsafe.Sizeof(d3)
	s4 := unsafe.Sizeof(d4)
	s5 := unsafe.Sizeof(d5)

	fmt.Printf("s1 = %d\n", s1)
	fmt.Printf("s2 = %d\n", s2)
	fmt.Printf("s3 = %d\n", s3)
	fmt.Printf("s4 = %d\n", s4)
	fmt.Printf("s5 = %d\n", s5)
}

It outputs (my machine is x64, pointer is 8 bytes):

s1 = 8
s2 = 8
s3 = 12
s4 = 24
s5 = 8

@wader
Copy link
Owner

wader commented Sep 1, 2022

Aha, yes i must have confused it with how a slice work

@wader wader mentioned this pull request Sep 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants