westley@hercules.uucp (03/14/90)
With apologies to those of you who already saw this in comp.software-eng -- I didn't edit the newsgroup header properly and wanted this to go into comp.lang.ada: In article <1771@awdprime.UUCP> sanders@sanders.austin.ibm.com (Tony Sanders) writes: >How do you do this in ADA? > > switch(n) { > case 0: > count++; > case 1: > ocount++; > case 2: > printf("%d %d\n",count,ocount); > break; > default: > printf("unknown n\n"); > break; > } > >See how I left out the breaks on purpose. > >In ADA you wouldn't be able to do this without duplicating either the >case-expression (they aren't always simple numbers) or the statements. > If the code is short enough that I can easily see any errors, I *would* duplicate it; if its not, I'd use a subprogram. In either case, we are talking about micro-efficiency here. Algorithm and data structure design (and ease of expression thereof) are much more important to the development and maintenance of good software than this kind of concern for what language is better for low-level efficiency. Personally, I find Ada to be especially good for this (and yes, I have used C extensively). Your mileage may vary. ---------------- Different topic follows: ------------------------- Now, for an Ada topic I have been struggling with and would love to hear advice from those who have done the equivalent in Ada. I don't want to hear from those who tell me to do it in C. We are building a real-time radar simulation on a distributed network of ~35 Sun workstations and ~35 68030 CPU boards (Motorola MVME147 specifically). Parts of the network will be Ethernet; the backbone will be FDDI. Now, for my question: I have approximately 200 unique messages that are transmitted over the net among all the various nodes. How do I send a particular Ada object of some arbitrary record type to another node while: 1) preserving strong typing -- I don't want to have to convert everything to some common structure such as an array of bytes 2) reducing messages to the smallest possible size -- I need to reduce the net traffic as much as possible -- as you know, there are numerous challenges relating to using variant record structures while trying to achieve this goal 3) avoiding giving global visibility to all message types to all program units I started out by writing a LAN interface package as a generic patterned after sequential_io. You instantiate it with the particular variant record structure that applies to the sender and receiver of that particular data. I also imported a function to determine the size of a particular record so that I wouldn't always be sending the maximum size of the record. The major problem with this is that I have many different combinations of messages to be sent to each destination. Here is a much simplified example of this problem. Suppose I have three elements that need to communicate: Element # Runs on Processor Needs message types --------- ---------------- ------------------- 1 A a, b, c 2 B b, c 3 C a, c I could build a variant record structure of message types a, b, and c. However, then Element 2 and 3 have visibility to message types they have no business seeing. I can't build three variant records (a-b-c, b-c, and a-c) because the record types will now be incompatible. Any ideas? Terry J. Westley Arvin/Calspan Advanced Technology Center P.O. Box 400, Buffalo, NY 14225 acsu.buffalo.edu!planck!westley@hercules Terry J. Westley Arvin/Calspan Advanced Technology Center P.O. Box 400, Buffalo, NY 14225 acsu.buffalo.edu!planck!westley@hercules
tom@hprmokg.HP.COM (Thomas Vachuska) (03/16/90)
I had a very similar problem, but I chose the dirty way of converting the records to byte arrays and then sending them. One advantage of doing it this way is that one can perform 'checksum' operation on the byte array to assure proper delivery, but otherwise this approach (as you mentioned) completely bypasses the type checking guards and is not very robust. I would be very interested in finding out how one can solve this problem (in Ada of course) a bit more elegantly. Thanks Thomas Vachuska
RCAPENER@cc.utah.edu (03/16/90)
In article <1990Mar13.185638.16143@planck.uucp>, westley@hercules.uucp writes: > With apologies to those of you who already saw this in > comp.software-eng -- I didn't edit the newsgroup header properly and > wanted this to go into comp.lang.ada: > > In article <1771@awdprime.UUCP> sanders@sanders.austin.ibm.com (Tony Sanders) writes: >>How do you do this in ADA? >> >> switch(n) { >> case 0: >> count++; >> case 1: >> ocount++; >> case 2: >> printf("%d %d\n",count,ocount); >> break; >> default: >> printf("unknown n\n"); >> break; >> } >> > > If the code is short enough that I can easily see any errors, I *would* > duplicate it; if its not, I'd use a subprogram. In either case, we are > talking about micro-efficiency here. > No you wouldn't, and that's because Ada doesn't fall through in the case statement like C does. Here is how you would really do it. >> switch(n) { >> case 0: >> count++; >> case 1: >> ocount++; >> case 2: >> printf("%d %d\n",count,ocount); >> break; >> default: >> printf("unknown n\n"); >> break; >> } if n = 0 then count := count + 1; end if; if n = 0 or n = 1 then ocount := ocount + 1; end if; if n = 0 or n = 1 or n = 2 then write... -- the equivalent here takes a few lines of code else write... -- ditto for this one end if; Lest you think this is necessarily going to generate more code, don't bet on it. The C may be clearer (personal opinion applies here), but both are going to generate about the same machine code, assuming that we are talking an optimizing Ada compiler that has been honed as long as the C compiler. Since I have nothing more to compare than VAX-VMS Ada and VAX-C, GNU C, or pcc to compare my observation is bound to be biased. From my perspective Ada is a real dog when speed of execution becomes an issue. Lest I be flamed, let me state that I like both C and Ada (prefer C most of the time). My only complaint is that for being as big as it is, Ada doesn't provide me with all the power of say, Common LISP! So let's stop flaming. If you like Ada and can find a job programming in it, by all means do so. The rest of us not working on DOD and other government projects have to get things done in the shortest amount of time possible, and it better run quick! Has anyone seen a good relational data base written in Ada instead of C? Don't flame RCAPENER! (I stole his account) flames to: dharvey@wsccs.weber.edu
garym@avocado.UUCP (Gary Morris) (03/18/90)
In article <51041@cc.utah.edu>, dharvey@wsccs.weber.edu writes: > In article <1771@awdprime.UUCP> sanders@sanders.austin.ibm.com (Tony Sanders) writes: >>How do you do this in ADA? >> >> switch(n) { >> case 0: >> count++; >> case 1: >> ocount++; >> case 2: >> printf("%d %d\n",count,ocount); >> break; >> default: >> printf("unknown n\n"); >> break; >> } >> >Here is how you would really do it. > >if n = 0 then > count := count + 1; >end if; >if n = 0 or n = 1 then > ocount := ocount + 1; >end if; >if n = 0 or n = 1 or n = 2 then > write... -- the equivalent here takes a few lines of code >else > write... -- ditto for this one >end if; > Here is how I would do it: if n in 0..2 then if n in 0..1 then if n = 0 then count := count + 1; end if; ocount := ocount + 1; end if; Int_IO.Put(count); Text_IO.Put(' '); Int_IO.Put(ocount); Text_IO.New_Line; else Text_IO.Put_Line("unknown n"); end if; If you're really concerned about the efficiency of the Ada code, let's take a closer look at what comes out. This last version is probably the most efficient way to code this in Ada. A total of 4 compares would be generated (2 for the "n in 0..2", 1 for the "n in 0..1"). In the previous Ada version there are 6 compares and all of them always executed (except the "or" might be short circuited). The C compiler will probably generate a table jump. But before it can index into the table it must make sure that the index is within the range 0..2, that takes 2 compares. Then we have to index into the table (a shift/load or equivalent) and branch. Ada C compares branches compares branches shift/ n executed taken total executed taken loads total -- -------- -------- ----- -------- -------- ------ ----- -1 1 1 2 1 1 0 2 0 4 1 5 2 2 2 6 1 4 2 6 2 2 2 6 2 3 2 5 2 2 2 6 3 2 1 3 2 1 0 3 4.2 4.6 We have 5 possibilities. Assuming they are of equal probability (a poor assumption, but we have no data, so let's use it for the sake of discussion), the average number of instructions is 4.2 for Ada and 4.6 for C. Of course, all instructions don't take the same amount of time to execute, branches taken are especially bad since they break the pipeline, and if the table jump code really did a shift (on a VAX) that would be awful (VAX shifts take as much time as about 4 add instructions) but it probably comes out as some indexed addressing mode. There are a number of other complications in determining which is fastest. I used VAX for the above example since I recently wrote an optimizing code generator for an Ada compiler targetted to the VAX. Targetting to other processors will give you different results. What is the distribution of the values on n? If it is usually going to be 0, for example, then we might code differently to take advantage of that. Additionally, this entire analysis must be redone if you change the number of case entries in the switch statement. In short we can't determine from comparing C and Ada source which is faster unless we know what kind of optimizations each compiler will do and what the instruction set of the target machine is like. In comparing these two languages what we have here is a tradeoff, we could either have the flexibility of the C switch statement where it is easy to add code to one case and not realize that another case may fall into it OR less flexibility in Ada but with less chance of introducing problems during future maintenance and enhancement. Since one of the goals of Ada was to reduce the life cycle costs of software, the bulk of which is spent in the maintenance phase, it makes sense that the Ada designers chose this form for this control structure. Finally, though, which one is fastest? It all depends on whether printf interpreting a control string is faster than the calls to Text_IO. The time spent in these control structures is totally insignificant compared to the time spent doing a subprogram call to printf or text_io. --GaryM -- Gary Morris Internet: garym@sugar.hackercorp.com Lockheed, Houston, Texas UUCP: uunet!sugar!garym Space Station Freedom Project Phone: +1-713-283-5195
cet1@cl.cam.ac.uk (C.E. Thompson) (03/20/90)
In article <256@avocado.uucp> garym@sugar.hackercorp.com writes: > ... >The C compiler will probably generate a table jump. But before it can index >into the table it must make sure that the index is within the range 0..2, that >takes 2 compares. ... A common fallacy. With any machine instruction set that you care to name, you will find that you can test a value for being in the range a..b with an add/subtract and one compare (and subsequent conditional branch): usually a subtract of 'a' and an unsigned comparison with 'b-a'. If a is zero, as here, the subtract disappears as well. Of course, this applies to the Ada range test as well. Chris Thompson JANET: cet1@uk.ac.cam.phx Internet: cet1%phx.cam.ac.uk@nsfnet-relay.ac.uk