Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
May 04, 2013 Avoid initializing a struct field. | ||||
---|---|---|---|---|
| ||||
Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work: struct Foo { int[42] buffer = void; int bar; } I know I can do this: Foo foo = void But then all fields are uninitialized. |
May 04, 2013 Re: Avoid initializing a struct field. | ||||
---|---|---|---|---|
| ||||
Posted in reply to jerro | On Saturday, 4 May 2013 at 18:11:03 UTC, jerro wrote:
> Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work:
>
> struct Foo
> {
> int[42] buffer = void;
> int bar;
> }
I think it's supposed to work. If it doesn't work, then I think it's a compiler bug.
What code have you used to test it, and what is the result you have seen?
With this code:
struct Foo {
int[42] buffer;
int bar;
}
int main() {
Foo f;
return f.bar;
}
DMD gives this code if I use void and if I don't use it:
// With void:
Dmain:
sub ESP, 0ACh
mov ECX, 02Bh
push ESI
mov ESI, offset FLAT:_D4temp3Foo6__initZ
push EDI
lea EDI, 8[ESP]
rep
movsd
mov EAX, 0B0h[ESP]
pop EDI
pop ESI
add ESP, 0ACh
ret
// Without void:
Dmain:
sub ESP, 0ACh
mov ECX, 02Bh
xor EAX, EAX
push EDI
lea EDI, 4[ESP]
rep
stosd
mov EAX, 0ACh[ESP]
pop EDI
add ESP, 0ACh
ret
Bye,
bearophile
|
May 04, 2013 Re: Avoid initializing a struct field. | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | > What code have you used to test it, and what is the result you have seen?
I was using this code:
extern(C) void foo(Foo* r)
{
Foo tmp;
*r = tmp;
}
And here is the generated assembly (when using "= void"):
push %rbp
mov %rsp,%rbp
sub $0xc0,%rsp
mov %rdi,-0x10(%rbp)
movabs $0x65a360,%rsi
lea -0xc0(%rbp),%rdi
mov $0x15,%ecx
rep movsq %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
lea -0xc0(%rbp),%rsi
mov -0x10(%rbp),%rdi
mov $0x15,%cl
rep movsq %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
movsb %ds:(%rsi),%es:(%rdi)
leaveq
retq
The problem here is that the code copies the entire object from some static address instead of just the fields that need to be initialized, and that can be a performance problem. The same is true for your void version.
I tried using float[42] instead of int[42] and found out that buffer actually isn't initialized to its default initializer if I use "= void" (the numbers were all 0 instead of NaN), but the performance cost is still there.
|
May 05, 2013 Re: Avoid initializing a struct field. | ||||
---|---|---|---|---|
| ||||
Posted in reply to jerro | Am Sat, 04 May 2013 21:00:17 +0200 schrieb "jerro" <a@a.com>: > I tried using float[42] instead of int[42] and found out that buffer actually isn't initialized to its default initializer if I use "= void" (the numbers were all 0 instead of NaN), but the performance cost is still there. Zero is the magic number. A struct with only binary zeros goes to the BS section in the executable (on Windows*), taking up no file space. So it serves a purpose as is. The .init property is a key part of the language. It is used in equality comparisons as well as a template that you can create carbon copies of. "T.init" might be the default value for a parameter of templated function, or it could be used as the initial value for new entries in a list/table with code relying on it being a constant. Your point is valid to some extent, but while logical it adds complexity and increases the odds that someone doesn't expect .init to be a _random_ value. Because that's what it is to templated code that is instantiated with such a struct. *) http://d.puremagic.com/issues/show_bug.cgi?id=7319 -- Marco |
May 06, 2013 Re: Avoid initializing a struct field. | ||||
---|---|---|---|---|
| ||||
Posted in reply to jerro | On Sat, 04 May 2013 14:11:02 -0400, jerro <a@a.com> wrote:
> Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work:
>
> struct Foo
> {
> int[42] buffer = void;
> int bar;
> }
>
> I know I can do this:
>
> Foo foo = void
>
> But then all fields are uninitialized.
Foo.init must exist, and be filled with *something*. Is it useful to FORCE buffer to not have 0 values? Or is it that you don't care what it has? In the latter, is it terrible that it's 0?
I tend to think that without the bar there, it could potentially be uninitialized (not sure if this is the case). But as long as it's there, buffer must also be initialized.
-Steve
|
May 06, 2013 Re: Avoid initializing a struct field. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 6 May 2013 at 15:15:47 UTC, Steven Schveighoffer wrote:
> On Sat, 04 May 2013 14:11:02 -0400, jerro <a@a.com> wrote:
>
>> Is there a way to avoid default initializing a struct field in D? The following doesn't seem to work:
>>
>> struct Foo
>> {
>> int[42] buffer = void;
>> int bar;
>> }
>>
>> I know I can do this:
>>
>> Foo foo = void
>>
>> But then all fields are uninitialized.
>
> Foo.init must exist, and be filled with *something*. Is it useful to FORCE buffer to not have 0 values? Or is it that you don't care what it has? In the latter, is it terrible that it's 0?
I don't care what it contains, I just want to avoid
initialization for performance reasons. I have something like
this:
struct Foo(size_t maxNItems)
{
Item[maxNItems] buffer;
size_t nItems;
size_t addItem(...){ ... }
void processItems(...){...}
}
The user of Foo can add up to maxNItems items and then run some
algorithm on them. Now say that Foo needs to support up to, say,
a thousand items, but in most cases just a few of them will be
added. In this case default initialization can take way more time
than the actual algorithm.
|
May 06, 2013 Re: Avoid initializing a struct field. | ||||
---|---|---|---|---|
| ||||
Posted in reply to jerro | On Mon, 06 May 2013 15:01:42 -0400, jerro <a@a.com> wrote: > On Monday, 6 May 2013 at 15:15:47 UTC, Steven Schveighoffer wrote: >> Foo.init must exist, and be filled with *something*. Is it useful to FORCE buffer to not have 0 values? Or is it that you don't care what it has? In the latter, is it terrible that it's 0? > > I don't care what it contains, I just want to avoid > initialization for performance reasons. The issue is that bar int in there. The compiler does not generate initialization code that sets up specific members. It basically has an init value, and it memcpy's that thing onto any uninitialized struct. If you want performance, initialize the memory (all of it) yourself. You can't do any worse :) -Steve |
Copyright © 1999-2021 by the D Language Foundation