Re: [go-nuts] Reduce memory usage via reduced padding?

2023-04-18 Thread Def Ceb
> FYI, there is an existing tool that can detect structs where fields 
> could be rearranged.
Interesting, I hadn't run into that before.

> I don't think that one helps, as struct sizes are always increased to 
> be a multiple of the required struct alignment. 
Ah, this is true. I was working off of go.dev/s/regabi and it seemed to 
imply that there's a lot less padding at the end of a struct.

> If there is a real performance difference, then, sure.
Fair enough, I'll try and check.

On Tuesday, April 18, 2023 at 7:56:07 PM UTC Ian Lance Taylor wrote:

On Tue, Apr 18, 2023 at 10:54 AM Def Ceb  wrote: 
> 
> While working on a personal project, I noticed that quite a few structs 
in the standard library, exported or otherwise, could have their memory 
footprint reduced by simply reordering their members so that padding 
required for alignment is reduced or even eliminated. 
> This can be in exported and unexported structs, and in both exported and 
unexported fields. 

FYI, there is an existing tool that can detect structs where fields 
could be rearranged. 

> go run 
golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest 
regexp 
/home/iant/go/src/regexp/backtrack.go:37:15: struct with 160 pointer 
bytes could be 152 
/home/iant/go/src/regexp/exec.go:24:12: struct with 16 pointer bytes could 
be 8 
/home/iant/go/src/regexp/exec.go:38:14: struct with 224 pointer bytes 
could be 216 
/home/iant/go/src/regexp/regexp.go:86:13: struct of size 160 could be 152 
/home/iant/go/src/regexp/all_test.go:430:17: struct with 56 pointer 
bytes could be 48 
/home/iant/go/src/regexp/all_test.go:482:20: struct with 48 pointer 
bytes could be 40 


> The Typeflag member of archive/tar.Header could be moved to the end of 
the struct, removing 7 bytes of padding 

I don't think that one helps, as struct sizes are always increased to 
be a multiple of the required struct alignment. 


> Examples of the third would, at the very least, break unkeyed struct 
literals, either at compile-time or silently at run-time, depending on the 
types in use and whether the instantiation uses a compatible literal. 
> While implementing the third example does not seem to go against the Go 1 
compatibility promise, it would seem like a fairly unpopular change if it 
caused large swathes of code utilizing unkeyed struct literals to stop 
compiling or, worse, break silently, and unless using them is prohibited at 
some point (at least for non-locally-defined structs), it'll probably be 
avoided. As far as I can tell, the status is similar for Go assembly. 

In general the Go 1 compatibility guarantee permits us to rearrange 
struct fields, and that is helped because "go vet" will warn about 
using an unkeyed struct literal for a struct defined in a different 
package. 


> Would a pull request with struct reordering to reduce padding be 
welcomed? 

Well, maybe. Where it makes sense. For many structs the size really 
doesn't matter, and the order of the fields makes the struct 
definition easier to read. If there is a real performance difference, 
then, sure. 

> Is there any chance of a policy of "try to avoid padding, if practical" 
being put in place for future additions to the standard library? 

Where it doesn't hurt readability, sure. 

> What about the gc compiler reordering struct member ordering at 
compile-time for the same effect, and in third-party code as well? 

Historically it's hard for compilers to know whether such field 
rearrangement is safe. The benefit you get, which is usually small, 
is not worth the slowdown in compile time. Better to follow the path 
you are already on: use a tool to find cases where it might make a 
difference. 

Ian 

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/bd93a76b-fd74-4641-ac7b-94652fdafa43n%40googlegroups.com.


Re: [go-nuts] Reduce memory usage via reduced padding?

2023-04-18 Thread Ian Lance Taylor
On Tue, Apr 18, 2023 at 10:54 AM Def Ceb  wrote:
>
> While working on a personal project, I noticed that quite a few structs in 
> the standard library, exported or otherwise, could have their memory 
> footprint reduced by simply reordering their members so that padding required 
> for alignment is reduced or even eliminated.
> This can be in exported and unexported structs, and in both exported and 
> unexported fields.

FYI, there is an existing tool that can detect structs where fields
could be rearranged.

> go run 
> golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest
>  regexp
/home/iant/go/src/regexp/backtrack.go:37:15: struct with 160 pointer
bytes could be 152
/home/iant/go/src/regexp/exec.go:24:12: struct with 16 pointer bytes could be 8
/home/iant/go/src/regexp/exec.go:38:14: struct with 224 pointer bytes
could be 216
/home/iant/go/src/regexp/regexp.go:86:13: struct of size 160 could be 152
/home/iant/go/src/regexp/all_test.go:430:17: struct with 56 pointer
bytes could be 48
/home/iant/go/src/regexp/all_test.go:482:20: struct with 48 pointer
bytes could be 40


> The Typeflag member of archive/tar.Header could be moved to the end of the 
> struct, removing 7 bytes of padding

I don't think that one helps, as struct sizes are always increased to
be a multiple of the required struct alignment.


> Examples of the third would, at the very least, break unkeyed struct 
> literals, either at compile-time or silently at run-time, depending on the 
> types in use and whether the instantiation uses a compatible literal.
> While implementing the third example does not seem to go against the Go 1 
> compatibility promise, it would seem like a fairly unpopular change if it 
> caused large swathes of code utilizing unkeyed struct literals to stop 
> compiling or, worse, break silently, and unless using them is prohibited at 
> some point (at least for non-locally-defined structs), it'll probably be 
> avoided. As far as I can tell, the status is similar for Go assembly.

In general the Go 1 compatibility guarantee permits us to rearrange
struct fields, and that is helped because "go vet" will warn about
using an unkeyed struct literal for a struct defined in a different
package.


> Would a pull request with struct reordering to reduce padding be welcomed?

Well, maybe.  Where it makes sense.  For many structs the size really
doesn't matter, and the order of the fields makes the struct
definition easier to read.  If there is a real performance difference,
then, sure.

> Is there any chance of a policy of "try to avoid padding, if practical" being 
> put in place for future additions to the standard library?

Where it doesn't hurt readability, sure.

> What about the gc compiler reordering struct member ordering at compile-time 
> for the same effect, and in third-party code as well?

Historically it's hard for compilers to know whether such field
rearrangement is safe.  The benefit you get, which is usually small,
is not worth the slowdown in compile time.  Better to follow the path
you are already on: use a tool to find cases where it might make a
difference.

Ian

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAOyqgcWowLcc1Ri5_j%2Bm2O8cz5ZyK0X_mwzYAqRRpUP2EJdd-Q%40mail.gmail.com.


[go-nuts] Reduce memory usage via reduced padding?

2023-04-18 Thread Def Ceb
Hello.
This is a request for comments on an idea I had.

While working on a personal project, I noticed that quite a few structs in 
the standard library, exported or otherwise, could have their memory 
footprint reduced by simply reordering their members so that padding 
required for alignment is reduced or even eliminated.
This can be in exported and unexported structs, and in both exported and 
unexported fields.
Examples as of Go 1.20.3, on an amd64 host:

   - moving the member h of the unexported struct crypto/sha1.digest to the 
   end would remove 4 bytes of padding between x and nx
   

   - moving the unexported minInputLen field of the regexp.Regexp struct to 
   right after matchcap will remove 6 bytes of padding
   - The Typeflag member of archive/tar.Header could be moved to the end of 
   the struct, removing 7 bytes of padding
   
Instances similar to the first two examples should be fairly frictionless, 
only affecting code that makes unsafe assumptions about standard library 
internals.
Examples of the third would, at the very least, break unkeyed struct 
literals, either at compile-time or silently at run-time, depending on the 
types in use and whether the instantiation uses a compatible literal.
While implementing the third example does not seem to go against the Go 1 
compatibility promise, it would seem like a fairly unpopular change if it 
caused large swathes of code utilizing unkeyed struct literals to stop 
compiling or, worse, break silently, and unless using them is prohibited at 
some point (at least for non-locally-defined structs), it'll probably be 
avoided. As far as I can tell, the status is similar for Go assembly.

As a benefit, this would lead to some small reductions in memory usage per 
instance of many structs, potentially leading to reduced need to grow the 
stack of threads. Though there are arguments that could be made against 
this as well, such as that some structs may contain multiple "groups" of 
data (which are not split up into multiple structs, for whatever reason) 
which shouldn't be split up, or that it could cause too much churn for too 
little benefit (I have not implemented nor benchmarked this at the moment), 
or that this is good, but it should be handled in the compiler instead.

I already made something to automatically generate a list of structs in the 
standard library which have padding, based on my project.

   1. Would a pull request with struct reordering to reduce padding be 
   welcomed?
   2. Is there any chance of a policy of "try to avoid padding, if 
   practical" being put in place for future additions to the standard library?
   3. What about the gc compiler reordering struct member ordering at 
   compile-time for the same effect, and in third-party code as well?
   

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/a7b6333a-2a73-41d1-850a-ebdaf6ddb67en%40googlegroups.com.