sal55
Posts: 59
Joined: Sat Sep 21, 2019 7:15 pm

Re: The Rust debate.

Wed Oct 02, 2019 12:59 pm

jahboater wrote:
Wed Oct 02, 2019 11:13 am
Heater wrote:
Wed Oct 02, 2019 9:58 am
Said project is a major reason I'm getting into Rust just now.
If you are talking about installing the latest GCC, I find it far far easier than Clang/LLVM.

On the Pi4, just start a simple script, wait for about 3 hours, and its all done. All the dependencies are automatically dealt with. And of course its optimized for your specific hardware.
(I've heard stories of Clang taking 30 hours to build on a 'Rock64' (competitor to RPi), although that might have been a 'debug' build.

As a contrast, here is my own (Windows) C compiler (a one-file self-contained C rendering): https://raw.githubusercontent.com/sal55 ... pi/bcc32.c. You build it on RPi4 using:

Code: Select all

tcc bcc32.c -obcc -lm -ldl
which takes 0.19 seconds. However, if you then try the result on itself (note this generates code for Windows on x64 only, so can only use -s or -c options on RPi):

Code: Select all

./bcc bcc32 -c
it takes 0.65 seconds. Using gcc-O3 will make it faster, but that takes 40 seconds. The result will be double the speed however.)

Heater
Posts: 13617
Joined: Tue Jul 17, 2012 3:02 pm

Re: The Rust debate.

Wed Oct 02, 2019 1:21 pm

sal55,

Ingenious. I always like a small fast C compiler.

You should start as new thread on these things. Other may be interested.
Memory in C++ is a leaky abstraction .

Heater
Posts: 13617
Joined: Tue Jul 17, 2012 3:02 pm

Re: The Rust debate.

Wed Oct 02, 2019 2:19 pm

STOP PRESS: Breaking news!

KEEP CALM AND CARRY ON C++.

Turns out that there is no need for Rust anymore. In it's relentless quest to absorb every feature of every language ever created C++ is now getting some features from Rust. I thought C++ had jumped the shark with the introduction of lambdas and closures but now there is more:

1) As of Clang 10 and new MSCVCC there is object lifetime analysis in C++.

See this presentation from CppCon published yesterday: Gábor Horváth, Matthias Gehre “Lifetime analysis for everyone”: https://www.youtube.com/watch?v=d67kfSnhbpA

That is to say the idea of "ownership" of data and static analysis, at compile time, of how it is created, mutated and disposed of and referenced. Somewhere in there is analysis intended to find use of null pointers and such. As far as I can tell this requires adding lifetime attribute annotations to objects. It is not intended to be 100% bullet proof. I have no idea what annotations in C++ are. Perhaps a master of modern C++ could try this out and report back.

2) On the table is a pattern matching syntax for C++. Pattern matching is that syntax you find in languages like Haskell and present in Rust's match constructs.

See: CppCon 2019: Michael Park “Pattern Matching: A Sneak Peek”: https://www.youtube.com/watch?v=PBZBG4nZXhk
Memory in C++ is a leaky abstraction .

User avatar
John_Spikowski
Posts: 1520
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: The Rust debate.

Wed Oct 02, 2019 4:03 pm

I LIKE patten matching built into a language. RegEx is too cryptic for me to use.

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Wed Oct 02, 2019 4:46 pm

Heater wrote:
Wed Oct 02, 2019 12:14 pm
jahboater,
Perhaps its turned off by default like integer overflow checks, or perhaps the array dimensions and indexes are known, or deducible, at compile time (my guess).
Nope. Checked at run time in debug and release builds:

Code: Select all

$ cat src/main.rs
fn main() {
    let my_array = vec![0, 1, 2, 3, 4];
    println!("{}", my_array[5]);
}
The array size and index are immediately obvious at compile time are they not? (Unless I have not understood the Rust!).
So yes there will be no run-time overhead.

What about the Rust equivalent of:

Code: Select all

int
main( int argc, const char *argv[] )
{
   char * my_array = malloc( atoi( argv[1] ) );
   my_array[argc] = 42;  
}
Reasonably, you would expect some considerable overhead to check that.
Last edited by jahboater on Wed Oct 02, 2019 5:07 pm, edited 3 times in total.

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Wed Oct 02, 2019 4:53 pm

Heater wrote:
Wed Oct 02, 2019 2:19 pm
1) As of Clang 10 and new MSCVCC there is object lifetime analysis in C++.
And GCC. Though I am not sure its in a released version yet.

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Wed Oct 02, 2019 4:56 pm

Heater,
The compiler does know the provenance of the pointers it creates. It can trace the ownership of those pointers through your source at compile time. It can therefore tell from your source that the pointer is never null or pointing at something invalid.

Of course at run time there is a malloc or whatever going on under the hood, which will return error indications which Rust will check. That is not a big thing for Rust to be doing automatically and is something you will be doing manually in C/C++ anyway.

Only when you use "unsafe" can you use pointers of unknown provenance. Like when interfacing to C libraries or hardware registers Then it is up to the programmer not to use them wrongly of course.
OK yes, I wondered if it did that. Its the only practical solution.
Otherwise, determining if a pointer is valid (other than non-NULL) is difficult without raising a seg fault!!!

Heater
Posts: 13617
Joined: Tue Jul 17, 2012 3:02 pm

Re: The Rust debate.

Wed Oct 02, 2019 5:45 pm

jahboater,
The array size and index are immediately obvious at compile time are they not?
Exactly.

However Rust does not complain about it at compile time. It fails at run time.

From which I conclude all the array bounds checking is done at run time.
Reasonably, you would expect some considerable overhead to check that
Not considerable. At least not in light of my musings above about all the branch prediction and parallel execution going on in modern processors:
https://www.raspberrypi.org/forums/view ... 0#p1545728

Certainly the fact that the C and Rust fft_bench run at the same speed indicates the performance hit of array bounds checking is lost in the noise.

Overflow checking however does slow the fft_bench down by 10 percent or so when enabled in release builds.
And GCC. Though I am not sure its in a released version yet.
Where did you read that? The guys in the presentation I linked to said it was not in GCC but they would be happy to help with the GCC devs if they want to adopt the object lifetime analysis code. That presentation was only days ago.
Memory in C++ is a leaky abstraction .

User avatar
paddyg
Posts: 2390
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: The Rust debate.

Wed Oct 02, 2019 9:34 pm

Reasonably, you would expect some considerable overhead to check that.
Out of curiosity I tried

Code: Select all

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut my_array: Vec<u8> = args[1].bytes().collect();
    my_array[args.len()] = 42;
    //println!("{:?}", my_array);
}
Approximation for your example, to see how the bounds checking is done. But talk about needles in haystacks! I've put the results online if you want to look at all 37,000 lines of disassembled code. The executable file (and stripped version) are there as well if you have a better way of viewing them unstripped, unstripped_dump, stripped and stripped_dump

PS I just overwrote an existing rust file sudoko/main.rs which is why that crops up. There is a movb 0x2a around line 312 but how the bounds checking happens is not so clear (it does check and gives a relevant panic message if too short a string is entered).
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Wed Oct 02, 2019 10:24 pm

paddyg wrote:
Wed Oct 02, 2019 9:34 pm
But talk about needles in haystacks! I've put the results online if you want to look at all 37,000 lines of disassembled code.
37,000 lines !!!!!! Eek.
For the C version, GCC removed everything and just did the return zero from main (2 instructions).

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Wed Oct 02, 2019 10:31 pm

Heater wrote:
Wed Oct 02, 2019 5:45 pm
Where did you read that? The guys in the presentation I linked to said it was not in GCC but they would be happy to help with the GCC devs if they want to adopt the object lifetime analysis code. That presentation was only days ago.
In the GCC dev list. There was quite a lot of talk about it a few months ago. Obviously never completed.

sal55
Posts: 59
Joined: Sat Sep 21, 2019 7:15 pm

Re: The Rust debate.

Wed Oct 02, 2019 10:36 pm

paddyg wrote:
Wed Oct 02, 2019 9:34 pm

Code: Select all

let mut my_array: Vec<u8> = args[1].bytes().collect();
  my_array[args.len()] = 42;
Approximation for your example, to see how the bounds checking is done. But talk about needles in haystacks! I've put the results online if you want to look at all 37,000 lines of disassembled code.
I've had the same problems. Then I might put special markers in the code that will hopefully be easy to find, eg. an assignment involving the constant 123456 or 0x123456 (or both). In the above example, perhaps change the 42 to a bigger magic number (may need to change the array element type).

But often it's a battle trying to outwit the compiler optimiser in order to ensure code is kept in that the compiler deems is unnecessary.

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Wed Oct 02, 2019 10:43 pm

Sal55,
sal55 wrote:
Wed Oct 02, 2019 10:36 pm
I've had the same problems. Then I might put special markers in the code that will hopefully be easy to find, eg. an assignment involving the constant 123456 or 0x123456 (or both). In the above example, perhaps change the 42 to a bigger magic number (may need to change the array element type).
Perhaps Clang has something like -fverbose-asm that includes the original source code interspersed with the generated assembler.

For GCC it works surprisingly well, despite optimization moving things around.
I have got used to just searching for the source code line when looking for the right place in the assembler output.

Heater
Posts: 13617
Joined: Tue Jul 17, 2012 3:02 pm

Re: The Rust debate.

Thu Oct 03, 2019 4:36 am

If you drop that code into the Godbolt Compiler Explorer, here: https://godbolt.org/z/8PJ72Q it shows all the generated assembler. If you click on the source line you are interested in and hit Cnt-F10 it takes you to the appropriate assembler lines, nicely highlighted in blue.

Godbolt is amazing.
Memory in C++ is a leaky abstraction .

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Thu Oct 03, 2019 8:28 am

Heater wrote:
Thu Oct 03, 2019 4:36 am
If you drop that code into the Godbolt Compiler Explorer, here: https://godbolt.org/z/8PJ72Q it shows all the generated assembler. If you click on the source line you are interested in and hit Cnt-F10 it takes you to the appropriate assembler lines, nicely highlighted in blue.

Godbolt is amazing.
Isn't it just! Good find.

That Rust code is all very bloated. You can see all the intrinsic's like "is_aligned_and_not_null" to check pointers which seem to be far bigger than they should be with many jumps and function calls. Worse, they are implemented as functions. Even the simple "non_null" check functions (there are several of them) involve two function calls! (I would have expected a simple test/jmp pair to precede a pointer de-reference - inline).

The Control-10 jump on "my_array[args.len()] = 42;" takes you to a large amount of unreadable code.

See this in Godbolt which I think is the equivalent C:
https://godbolt.org/z/__rJ4H
Control-F10 on the "my_array[argc] = 42;" line takes you directly to:-

mov BYTE PTR [rax+rbx], 42

On line 20 just after the "call malloc"

Sorry, if raw speed and/or small code size are important for a project, I'll stick with C, C++ or Fortran.

User avatar
John_Spikowski
Posts: 1520
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: The Rust debate.

Thu Oct 03, 2019 8:57 am

Sorry, if raw speed and/or small code size are important for a project, I'll stick with C, C++ or Fortran.
Wise advice.

Portability is also a trait of C I enjoy.

Heater
Posts: 13617
Joined: Tue Jul 17, 2012 3:02 pm

Re: The Rust debate.

Thu Oct 03, 2019 10:48 am

John_Spikowski,
Portability is also a trait of C I enjoy.
Portability is very important to me as well. I don't want to even think about a language/language system that is not cross platform.

Which is why Rust is on my Radar, it's a fairly new language to the scene but it can already build code on and for a huge range of architectures and platforms: https://forge.rust-lang.org/release/pla ... pport.html

All the way from top end Intel servers down to tiny micro-controllers like the 16-bit MSP430.https://forge.rust-lang.org/release/pla ... pport.html

Which is to be expected as Rust gets the cross-platform capability from using the LLVM back end.
Memory in C++ is a leaky abstraction .

sal55
Posts: 59
Joined: Sat Sep 21, 2019 7:15 pm

Re: The Rust debate.

Thu Oct 03, 2019 11:29 am

Heater wrote:
Thu Oct 03, 2019 10:48 am
John_Spikowski,
Portability is also a trait of C I enjoy.
Portability is very important to me as well. I don't want to even think about a language/language system that is not cross platform.

Which is why Rust is on my Radar, it's a fairly new language to the scene but it can already build code on and for a huge range of architectures and platforms: https://forge.rust-lang.org/release/pla ... pport.html

All the way from top end Intel servers down to tiny micro-controllers like the 16-bit MSP430.https://forge.rust-lang.org/release/pla ... pport.html

Which is to be expected as Rust gets the cross-platform capability from using the LLVM back end.
Supporting odd architectures is part of the reason C's type system is such a mess. It cannot even commit itself to the number of bits in a 'char' (or whether it is signed or unsigned); or whether 'long' is 32 or 64 bits, and is compatible with 'int' or 'long long int', or neither; or whether 'int' is 16 bits, or 32, or something else entirely; or whether 'uint32_t' is defined on top of 'unsigned int' or 'unsigned long' or something else, or even if it has 32 bits. Anyway, you get the idea!

Whereas more modern languages that have ranges of fixed-width types have standardised on widths of 8, 16, 32 and 64 bits, including Rust.

That MSP device may just fit into that scheme, but odder ones might not.

(Note that LLVM itself allows any integer bit-widths even up to 8388608 bits wide (2**23). I'm not sure how that works out in actual code.)

User avatar
John_Spikowski
Posts: 1520
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: The Rust debate.

Thu Oct 03, 2019 11:41 am

ScriptBasic (ANSI C) ported to 64 bit and ARM with nothing more than a gcc command line addition.

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Thu Oct 03, 2019 11:42 am

sal55 wrote:
Thu Oct 03, 2019 11:29 am
Whereas more modern languages that have ranges of fixed-width types have standardized on widths of 8, 16, 32 and 64 bits, including Rust.
Precisely what C did 20 years ago ...

C99 introduced exact width types and others such as int_fast and int_least.
Forget about what they may map onto, it is of no interest to the programmer.
(sure int64_t may be slow on a 32-bit platform, but it works perfectly. There is no need for the code to be aware.)

CHAR_BIT is fixed at 8 (when did you last see a computer with 6 or 9 bit bytes?)

Yes the older types such as long may change between 32 and 64 bit platforms, which is sometimes useful.
Last edited by jahboater on Thu Oct 03, 2019 11:47 am, edited 1 time in total.

User avatar
PeterO
Posts: 5069
Joined: Sun Jul 22, 2012 4:14 pm

Re: The Rust debate.

Thu Oct 03, 2019 11:47 am

sal55 wrote:
Thu Oct 03, 2019 11:29 am

Whereas more modern languages that have ranges of fixed-width types have standardised on widths of 8, 16, 32 and 64 bits, including Rust.

Code: Select all

#include <sdtint.h>

int8_t  a;

......
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

Heater
Posts: 13617
Joined: Tue Jul 17, 2012 3:02 pm

Re: The Rust debate.

Thu Oct 03, 2019 11:48 am

John_Spikowski,

It's lucky Richard Stallman started GCC over 30 years ago and inspired people to spend thousands/millions of man hours on it to make that possible.
Memory in C++ is a leaky abstraction .

jahboater
Posts: 4765
Joined: Wed Feb 04, 2015 6:38 pm

Re: The Rust debate.

Thu Oct 03, 2019 11:51 am

John_Spikowski wrote:
Thu Oct 03, 2019 11:41 am
ScriptBasic (ANSI C) ported to 64 bit and ARM with nothing more than a gcc command line addition.
I think that's rather impressive.

I'd like to know what that command line option was ???

User avatar
John_Spikowski
Posts: 1520
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: The Rust debate.

Thu Oct 03, 2019 11:59 am

I think Peter Verhas's design and unlimited expansion is an example of vision at its best.

plugwash
Forum Moderator
Forum Moderator
Posts: 3462
Joined: Wed Dec 28, 2011 11:45 pm

Re: The Rust debate.

Thu Oct 03, 2019 12:00 pm

jahboater wrote:
Thu Oct 03, 2019 11:42 am
C99 introduced exact width types and others such as int_fast and int_least.
Forget about what they may map onto, it is of no interest to the programmer.
Unfortunately the C99 typedefs don't fully solve the problem because of C's boneheaded promotion and overflow rules, consider for example.

Code: Select all

uint16_t a = 0xFFFF;
uint16_t b = 0xFFFF;
uint16_t c = a * b;
You might expect this code to be well-defined, after all arithmetic on unsigned types has well-defined wraparound semantics.

Unfortunately promotion steps in to mess things up. If int is 16 bits or less then no promotion happens and the code is well-defined. If int is more than 32 bits then promotion happens, but is harmless. However if int is 32 bits then this code has undefined behaviour.

Return to “Other programming languages”