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