division of objects into classes and structures is bad

Weed resume755 at mail.ru
Tue Dec 30 08:20:42 PST 2008


Don пишет:
> Weed wrote:
>> Don пишет:
>>> Weed wrote:
>>>> Don пишет:
>>>>> Weed wrote:
>>>>>> Denis Koroskin пишет:
>>>>>>
>>>>>>>>  80490eb:       8d 85 6c fe ff ff       lea    -0x194(%ebp),%eax
>>>>>>>>  80490f1:       50                      push   %eax
>>>>>>>>  80490f2:       8d 85 2c fb ff ff       lea    -0x4d4(%ebp),%eax
>>>>>>>>  80490f8:       e8 67 ff ff ff          *call   8049064*
>>>>>>>>  80490fd:       e8 62 ff ff ff          *call   8049064*
>>>>>>>>     return c2.i;
>>>>>>>>  8049102:       8b 85 cc fc ff ff       mov    -0x334(%ebp),%eax
>>>>>>>> ...
>>>>>>>>
>>>>>>>>
>>>>>>>> (in 80490f8 and 80490fd simply two calls successively)
>>>>>>>>
>>>>>>>> If structures and classes were same that excellent optimization in
>>>>>>>> any
>>>>>>>> case would turn out
>>>>>>> If that's your use case, then your should seriosly reconsider using
>>>>>>> struct instead of class for your objects.
>>>>>> Classes always give such overhead if them to use in such quality. For
>>>>>> example, classes basically cannot be used as any mathematical objects
>>>>>> using overload of arithmetics. But also not only arithmetics, it
> it is
>>>>>> simple as a good example.
>>>>>>
>>>>>>> Alternatively, you can use +=
>>>>>>> instead.
>>>>>> Here yes, but if I add classes of different types? Then not to escape
>>>>>> any more from creation of the temporary object in the heap.
>>>>>>
>>>>>>> Other than that, this is not a convincing argument.
>>>>>>>
>>>>>>> Reading many of your posts I came to a conclusion that you are
>>>>>>> shortsighted and too crazy about performance. What you care about
> is a
>>>>>>> premature optimization, which is a root of all the evil. You should
>>>>>>> ensure that your programm is complete and correct, first and *then*
>>>>>>> start doing profiling and optimizations.
>>>>>> The program is already ready. It entirely consists of the various
>>>>>> mathematics. Approximately %30 times of performance are spent for
>>>>>> similar superfluous work. On C++ the program will work on %30
> faster (I
>>>>>> hope :)) and on D I am will turn out to do nothing with it.
>>>>>>
>>>>>>
>>>>>>> Going back to the topic, dividing user types into two cathegories
>>>>>>> (structs and classes) is considered modern and right.
>>>>>> I do not accept such argument:)
>>>>>>
>>>>>>> Some languages
>>>>>>> lack structs support at all (e.g. Java), but structs are too useful
>>>>>>> for
>>>>>>> optimization and language interoperation to drop them in a systems
>>>>>>> programming language. Some lack classes and try doing everything
> with
>>>>>>> structs (C). D takes the best of both worlds.
>>>>>> Probably I have not understood something, but I do not suggest to
>>>>>> refuse
>>>>>> structures in general. I suggest to allow to create classes on a
> stack
>>>>>> as it is made in C++. That is actually to make structures and classes
>>>>>> same, than they and are, for example, in C++.
>>>>>>
>>>>>> In the initial message I have shown that for perfomance important
> that
>>>>>> the class could be transferred and on value. And it not artful
>>>>>> premature
>>>>>> optimisation - objects on value always so are transferred, all
>>>>>> programmers know it and use when do not wish to allocate a place in a
>>>>>> heap, that is usually always when the object will live in {}.
>>>>>>
>>>>>> Besides, a class in a stack it is normal - keyword addition
> "scope" for
>>>>>> classes too speaks about it.
>>>>>>
>>>>>> Rigidly having divided classes and structures D deprives of the
>>>>>> programmer of some possibilities which give it C++-like languages. I
>>>>>> consider that such languages should give all possibilities which
> allows
>>>>>> CPU but hiding concrete architecture, otherwise I would choose less
>>>>>> difficult in use language.
>>>>> Use classes if you want polymorphism. Otherwise, use structs. It's a
>>>>> clear distinction, which is not at all arbitrary -- there are
>>>>> significant implications for the generated code.
>>>> And if polymorphism is necessary and such calculations are necessary as
>>>> I have above described? To emulate polymorphism with the mixins? Or
>>>> simply to reconcile to such obvious losses?
>>>>
>>>> I about that that division into classes and structures in language D
>>>> automatically reduce perfomance of programs. Unlike languages where
> this
>>>> division is not present (C++).
>>> I agree with you that there's a problem, but I think you're wrong about
>>> the solution. C++ suffers from severe problems with creation of
>>> temporaries in expressions. The problem occurs whenever you have heap
>>> allocations inside an object which does operator overloading.
>>
>> Nothing can be done with it in any case.
>> If the class uses in itself dynamic allocation through "new" that this
>> memory will be allocated in a heap. But time in a class is used such way
>> of allocation that for this purpose there are reasons.
> 
> You certainly can do something about it. By rearranging the expression,
> you can avoid the unnecessary creation of temporaries.

I consider that it wrong and I quote myself:
=========
> > Alternatively, you can use +=
> > instead.

Here yes, but if I add classes of different types? Then not to escape
any more from creation of the temporary object in the heap.
=========


> 
>>> Sure, in
>>> the simple case you mentioned, using a struct works because the size of
>>> the data is small.
>>
>> No. Structure used only because it is the type transferred on value in D.
> 
> That's not what I meant. You can have an object which contains a pointer
> to heap-allocated data (eg, it could contain a dynamic array). Turning
> the object from a class into a struct does not remove the heap allocation.
> 

And still the object can to access, for example, to a file system in the
constructor. :) But if the programmer has written object so that it was
fast (did not use call to a heap) that all will be ok.

>>
>>> But it general, it's not possible to avoid the heap
>>> allocation, and so in C++ you'll still have a problem.
>>>
>>> The creation of temporaries during expressions is something I'm
>>> currently working on solving. The case you mentioned is addressed by a
>>> proposal I made long ago:
>>> http://d.puremagic.com/issues/show_bug.cgi?id=124
>>>
>>>  c2 = c1 + c1 + c1;
>>>
>>> would be transformed into
>>> t1 = c1 + c1;
>>> t1.opAddAssign(c1);
>>> c2 = t1;
>>> which gets rid of the temporary heap allocation.
>>> I don't think you could ever get rid of the heap allocation for c2 since
>>> (a) c2 might be null, initially;
>>
>> In this case opAdd returns the result object to which the name c2 will
>> be assigned.
>>
>>> and (b) c2 might be pointing to the
>>> same place as c1.
>>
>> There will be the same as (a).
> 
> My point is that you might hope to be able to avoid memory allocation
> entirely, putting the new value of c2 in-place, but case (a) and (b)
> make it impossible. There will always be ONE heap allocation.

If class are stored in a stack that there will be no.

> 
>> If it is necessary to equate to the existing object (for example that it
>> did not change the position in memory) it is possible to overload that
>> the operator [] = and to make so: c2 [] = c1 + c1 + c1;
>>
>>> Nonetheless, I'd like to do better than this.
>>> Consider:
>>> C c1, c2, c3;
>>> c3 = c1*5 + c2/6;
>>>
>>> The optimal solution depends on whether in-place operations are possible
>>> or not. Interestingly, X+=Y is more efficient than X=X+Y only if
>>> in-place operations are possible; there's no point in defining it if
>>> in-place is impossible.
>>
>> There can be I something do not understand, but the decision should be
>> more the general than optimization of an overload of operators.
>> Eventually, the overload of operators is simply syntactic sugar.  I used
>> them simply as an example.
> 
> OK, then you're getting into another issue...
> 
>> It is possible to think up other example where there is no overload:
>>
>> space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords;
>>
>> In this example we create a temporary class "path", create temporary
>> class "checkpoint" and we take coords of checkpoint of this path. It is
>> not expedient to us to store all this path and checkpoint because it is
>> vary.
> 
> I fail to see how D's distinction between classes and structs has any
> bearing on this. The optimisations you're talking about are only
> possible in the presence of polymorphism, in cases where you can prove
> that polymorphism is not being used! I suspect that if you're
> encountering this issue in speed-critical code, there's a problem with
> your design.
> 

Quite right, if polymorphism I would not be necessary to me did not use
classes, it is obvious. All the rest that you have told it the common
words so experts in marketing speak. :)

I give concrete examples from a life where D is bad. You see a design
problem in the code resulted above?


By the way, one of serious problem: if necessary it is difficult enough
to alter a class in structure and vice versa. Insufficiently simply to
change the keyword. And it is serious, it is not necessary to me to tell
about planning.


>>> Case 1: in-place operations are possible, += exists. All operators
>>> include destination.
>>> Convert to t1 = c2/6; c3 = c1*5;  c3+=t1;
>>> ---
>>> LocalHeap h;
>>> t1 = h.new(C);  // create on LocalHeap h
>>> t1.operatorWithDestination("/")(c2, 6);
>>> C t2 = new C;  // create on heap
>>> t2.operatorWithDestination!("*")(c1, 5);
>>> c3 = t2.operatorAssign!("+")(t1); // in-place += operation on heap
>>> h.releaseAll;
>>> ---
>>> Case 2: in-place operations are impossible, += doesn't exist.
>>> ---
>>> LocalHeap h;
>>> t1 = c1.operatorTemporary!("*")(5, h); // create on local heap
>>> t2 = c2.operatorTemporary!("/")(6, h); // create on local heap
>>> c3 = t1.operator!("+")(t2); // create on heap
>>> h.releaseAll;
>>> ---
>>> It's far too complicated at present to be workable, but that's the basic
>>> idea.
>>
>> Whether tells word introduction "scope" and such attempts of
>> optimization about that that the design of objects in D is wrong? ]:)
> 
> No, I think the design of objects in D is sound. I think operator
> overloading in both D and C++ is incomplete.

It simply sugar, it is not necessary to forget



More information about the Digitalmars-d mailing list