Bug 97506 - GooString wastes 4 bytes on 64-bit systems
Summary: GooString wastes 4 bytes on 64-bit systems
Status: RESOLVED FIXED
Alias: None
Product: poppler
Classification: Unclassified
Component: general (show other bugs)
Version: unspecified
Hardware: Other All
: medium normal
Assignee: poppler-bugs
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-08-27 04:30 UTC by Jakub Alba
Modified: 2016-09-06 21:15 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


Attachments
[PATCH 1/2] goo: fix GooString::STR_STATIC_SIZE calculation (1.21 KB, patch)
2016-08-27 04:31 UTC, Jakub Alba
Details | Splinter Review
[PATCH 2/2] goo: check at compile time if GooString has the right size (953 bytes, patch)
2016-08-27 04:35 UTC, Jakub Alba
Details | Splinter Review
[PATCH] check GooString size (only for 64-bit platforms) (1.01 KB, patch)
2016-08-27 23:06 UTC, Jakub Alba
Details | Splinter Review

Description Jakub Alba 2016-08-27 04:30:21 UTC
GooString has 3 fields:
char sStatic[STR_STATIC_SIZE];
int length;
char *s;

32-bit system without the patches:
STR_STATIC_SIZE:      24
sizeof(MemoryLayout): 12
sizeof(char*):         4
sizeof(int):           4
sizeof(GooString):    32
------------------------
Used = STR_STATIC_SIZE + sizeof(int) + sizeof(char*) = 24 + 4 + 4 = 32 out of 32 taken (100% efficiency)

64-bit system without the patches:
STR_STATIC_SIZE:      16
sizeof(MemoryLayout): 24
sizeof(char*):         8
sizeof(int):           4
sizeof(GooString):    32
------------------------
Used = STR_STATIC_SIZE + sizeof(int) + sizeof(char*) = 16 + 4 + 8 = 28 out of 32 taken (87.5% efficiency)

Right now STR_STATIC_SIZE is calculated using class MemoryLayout which doesn't help, but only makes it harder due to memory alignment performed by the compiler (sizeof(MemoryLayout) on a 64-bit system >= the sum of MemoryLayout's fields sizes).

With my patches sizeof(GooString) is still == 32, and there are no wasted bytes.
Comment 1 Jakub Alba 2016-08-27 04:31:13 UTC
Created attachment 126067 [details] [review]
[PATCH 1/2] goo: fix GooString::STR_STATIC_SIZE calculation
Comment 2 Jakub Alba 2016-08-27 04:35:15 UTC
Created attachment 126068 [details] [review]
[PATCH 2/2] goo: check at compile time if GooString has the right size

This patch makes it harder to introduce bugs related to GooString size.
(Wouldn't really prevent this one, because I think this one couldn't be automatically detected without a special static code analyzer or something like that.)
Comment 3 Jakub Alba 2016-08-27 19:45:46 UTC
If the current behavior is intended to keep length at aligned offset, then maybe GooString could be made bigger, because 16 bytes for sStatic on a 64-bit system (they usually have a bit more RAM than 32-bit systems, so it could be made use of) seems a bit small to me. I've tried that by defining STR_FINAL_SIZE as:

static const int STR_FINAL_SIZE = 8 * sizeof(char*); // 32 on a 32-bit system, 64 on a 64-bit one

, but for some reason it breaks PDFDoc construction in PDFDocFactory (a problem in a "new" operator function - not sure which though). If you say the above line is desirable, then I could take some time and debug the issue.
Comment 4 Albert Astals Cid 2016-08-27 22:04:13 UTC
elf-dissector disagrees with your patch

class GooString // location: /home/tsdgeos/devel/poppler/goo/GooString.h:49
{
    char[36] sStatic; // member offset: 0, size: 36, alignment: 1
    int length; // member offset: 36, size: 4, alignment: 4
    char* s; // member offset: 40, size: 8, alignment: 8
}; // size: 48, alignment: 8
Used bytes: 48/48 (100%)
Used bits: 384/384 (100%)

This is with your patch, GooString is now 48 bytes instead of 32. 

but agrees with your bug (without the patch it says)

class GooString // location: /home/tsdgeos/devel/poppler/goo/GooString.h:49
{
    char[16] sStatic; // member offset: 0, size: 16, alignment: 1
    int length; // member offset: 16, size: 4, alignment: 4
    // 4 byte(s) padding
    char* s; // member offset: 24, size: 8, alignment: 8
}; // size: 32, alignment: 8

Used bytes: 28/32 (87.5%)
Used bits: 224/256 (87.5%)
Comment 5 Jakub Alba 2016-08-27 23:06:16 UTC
Created attachment 126076 [details] [review]
[PATCH] check GooString size (only for 64-bit platforms)
Comment 6 Jakub Alba 2016-08-27 23:07:54 UTC
(In reply to Albert Astals Cid from comment #4)
> elf-dissector disagrees with your patch
> 
> class GooString // location: /home/tsdgeos/devel/poppler/goo/GooString.h:49
> {
>     char[36] sStatic; // member offset: 0, size: 36, alignment: 1
>     int length; // member offset: 36, size: 4, alignment: 4
>     char* s; // member offset: 40, size: 8, alignment: 8
> }; // size: 48, alignment: 8
> Used bytes: 48/48 (100%)
> Used bits: 384/384 (100%)
> 
> This is with your patch, GooString is now 48 bytes instead of 32. 
> 
> but agrees with your bug (without the patch it says)
> 
> class GooString // location: /home/tsdgeos/devel/poppler/goo/GooString.h:49
> {
>     char[16] sStatic; // member offset: 0, size: 16, alignment: 1
>     int length; // member offset: 16, size: 4, alignment: 4
>     // 4 byte(s) padding
>     char* s; // member offset: 24, size: 8, alignment: 8
> }; // size: 32, alignment: 8
> 
> Used bytes: 28/32 (87.5%)
> Used bits: 224/256 (87.5%)

Are you sure elf-dissector is right? I don't know this tool, but when I run something with poppler with the above patch, it doesn't complain.
Comment 7 Albert Astals Cid 2016-09-05 14:29:59 UTC
Well, it's following your math, no?

static const int STR_STATIC_SIZE = STR_FINAL_SIZE - sizeof(int) - sizeof(char*);
so 
STR_STATIC_SIZE = 32 - 4 + 8 = 36
so if STR_STATIC_SIZE is already 36 the whole thing will be bigger than 32, no?
Comment 8 Jakub Alba 2016-09-05 18:20:45 UTC
(In reply to Albert Astals Cid from comment #7)
> Well, it's following your math, no?
> 
> static const int STR_STATIC_SIZE = STR_FINAL_SIZE - sizeof(int) -
> sizeof(char*);
> so 
> STR_STATIC_SIZE = 32 - 4 + 8 = 36
> so if STR_STATIC_SIZE is already 36 the whole thing will be bigger than 32,
> no?

No. There is no addition. STR_STATIC_SIZE = 32 - 4 - 8 = 20.

My only worry here is performance (due to memory alignment). Benchmarks could help, but recently I don't have time for figuring out how to properly benchmark it (or for anything else for that matter). So I suggest letting it hang here until someone, who has time for that, benchmarks it.

Cheers,
Jakub
Comment 9 Albert Astals Cid 2016-09-06 09:28:38 UTC
Sorry that's my fault for being silly and trying to apply the patch manually.

I'll try to go over this soon but given i'm taking a 3 week holiday away from a computer starting on friday i'm not sure i'll manage.
Comment 10 Albert Astals Cid 2016-09-06 21:15:31 UTC
pushed


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.