C# was created under the leadership of Anders Hejlsberg who happens to be the guy behind TurboPascal.
That's almost enough to make me overlook the MicroSoft connection:)
@Jazzed, glad to hear we are breaking new ground here.
I'll update the demo code, hopefully today, to spin off a new thread to monitor for serial IO. I built the GUI to handle textbox updates from a secondary thread. I imagine threading works the same in Linux.
If you had a good old fashioned mother board with serial ports on it they would be ttyS0 and ttyS1 at least.
Or plug a real serial port card in and they will be in use.
Not sure why they are still coming up for modern motherboards with no serial ports though.
If you can show me how to detect the various Parallax chips, Propeller, Basic Stamps, etc... I can do some detection for the uM-FPU and Various GPS modules.
I am including a new project to test a bit more in mono. This one is going to be a GUI not much is working yet, just getting the look and feel right now. I put
C# has untyped variables like VB.net for ease of use in database applications.
Jazzed. One correction, C# is a strongly typed language... there are no objects that are untyped. I think you might be referring to two objects where type is inferred and not exactly specified by the developer, Var and Dynamic. One is inferred at compile time based on usage and the other at runtime, but they are most definetly strongly typed.
If you can show me how to detect the various Parallax chips, Propeller, Basic Stamps, etc...
I'm not sure how to detect a STAMP or Prop without having something running on the device. I know that STAMP has the ability to update the STAMP directive when the code is run. I'm not sure how that works and I'm not sure about the Prop. I am sure someone can let us know.
C# was created under the leadership of Anders Hejlsberg who happens to be the guy behind TurboPascal.
That's almost enough to make me overlook the MicroSoft connection:)
When I heard that Anders Hejlsberg (who designed Delphi as well as TurboPascal) had left Borland for Microsoft, I complained to my boss that now he would be making evil products. My boss' response was "at least they will be well-designed evil products."
In Anders' defense, it looks like he made a pretty good career move.
Jazzed. One correction, C# is a strongly typed language... there are no objects that are untyped. I think you might be referring to two objects where type is inferred and not exactly specified by the developer, Var and Dynamic. One is inferred at compile time based on usage and the other at runtime, but they are most definetly strongly typed.
Bill
C# is strongly typed in that all types are defined as types including the var type which is typed by the compiler implicitly but not typed by the programmer. Programmers do all kinds of typing
Feel like I cheated a little... I updated the serial port demo to include a timer. The timer is invoked when a serial port is successfully opened. The serial port is read every 1/2 second, if data is present, the values are displayed in the terminal. http://www.agaverobotics.com/serialportdemo.zip
If you click the send button with no data, "Hello World" is sent.
If need be I can wire up a more comprehensive data received handler.
Propeller test code.
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
DAT
message byte "Hello World"
OBJ
serial : "FullDuplexSerial"
PUB Main | command
serial.Start(31, 30, 0, 115200)
repeat
command := serial.rx
serial.tx(command)
'serial.str(@message)
'Pause(250)
PRI Pause(Duration)
waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
return
C# is strongly typed in that all types are defined as types including the var type which is typed by the compiler implicitly but not typed by the programmer. Programmers do all kinds of typing
There has been talk occasionally of C# and .NET for embedded systems. Perhaps even the Prop.
I have just been exercising a version of the fft_bench in C#, on a PC admittedly.
Turns out that using mono under C# the FFT is 60% slower than the C version. Now that is with a full up JIT compiler. I suspect it would be another 100 times slower if there were only a byte code interpreter on a small embedded system.
Strangely enough when I try to use the mono Ahead Of Time Compiler (AOT) it gets even slower!
All of which does not look good for C# on embedded systems.
Before I put up the results does anyone know any tricks to get C# programs with mono and the AOT to run faster?
Before I put up the results does anyone know any tricks to get C# programs with mono and the AOT to run faster?
If your program uses classes, replacing them with structs might improve performance.
Theoretically struct is not instantiated the same way as a class and has direct references.
Bill (wjsteele) might have more tricks.
If I understand you cannot have any functions in C# that are not members of a class, that is to say "methods".
As such the entire fft_bench is incorporated into a single class and are "static".
This version has no other structs or classes.
IIRC all you have to do is change the keyword Class to Struct.
A struct does not use double indirection to methods and data members.
I can't remember all the differences just now.
I just found this on the MSDN it might give some clue to what is going on in C# if you are not familiar with the way it works. Writing Faster Managed Code
Ha! Not so fast. Strangely enough results look a little better on my home PC. Also with mono on Debian.
Here the fft_bench in C runs in 81us and in C# it's 116us. That's only 43% slower. Again trying to use AOT slows it down.
Changing the only "class" to "struct" makes not even 1us difference.
I don't know what else can be done to speed this up. The idea of the thing is to, as far as possible, keep to the same code structure as the original Spin version. Same operators, types, loops, etc etc. This makes for a somewhat valid comparison between languages and CPUs.
To that end I tried to add only the minimum required by C# to get it to run.
Anyway the code is attached here for anyone who is interested.
Here the fft_bench in C runs in 81us and in C# it's 116us. That's only 43% slower. Again trying to use AOT slows it down.
If you use the "Native Image Generator Tool" NGen.exe,
Native Image Generator Tool (Ngen.exe)
Creates a native image from a managed assembly and installs it into the native image cache on the local computer.
Code is supposedly faster too, but I have never used it. It is in the .NET Framework SDK. , NOTE: SDK I'm not sure if it comes with just the .NET framework install.
Don't forget that over here in Linux land we don't have .NET Framework SDK or NGen.
However mono does have AOT, Ahead Of time Compilation. So,
1) Let monodevelop compile your code to a .exe
2) Run mono over it with some funky options that compile the bytecodes to native code and puts that into a .so library file.
3) Run the .exe with some more funky options to mono which causes it not to JIT.
Problem is that actually makes for slower run time!!!
I have to get another linux box, I used to run S.u.S.E. 5.1 to 6.3 which seems like ages ago. I'll have to try out the debain installs. I could never get my hardware to work though, mainly video drivers for X so I just reinstalled MS Windoz. On S.u.S.E. I got it all to work but had to recompile the kernal a few times to get everything right.
Do the newer versions of Debain have kernal sources included with the disks/downloads or is it seperate now?
No idea if the Linux sources are on any Debian install disk but once you have a minimal install those are only an "apt-get" away, as is everything else.
I'm not familar with the technical details of Mono, but if it has a GAC (Global Assembly Cache) like the one in Microsoft's .NET Framework... using AOT should be faster because it doesn't have to verify the assembly. The problem is that if it is not in the GAC, the assembly must be verified before execution to insure security, which actually parses and validates the MSIL (by computing a hash)... even if it's already been compiled to native code. Adding it to the GAC validates it ahead of time so it naturally speeds it up.
Perhaps that's why you are seeing slower execution times.
Here's my FFT results. I'm not sure how to interpret the output. I have to head to work. I'll look closer at the source later today.
Linux box (AMD Sempron 2200, 1.5GiB)
Compiled in debug mode
Hello World!
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 1541 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 381 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 374 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 377 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
Press any key to continue...
Linux box (AMD Sempron 2200, 1.5GiB)
Compiled in release mode
Hello World!
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 2185 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 383 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 619 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 375 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 380 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 10000000
Timer is accurate within 100 nanoseconds
Press any key to continue...
Windows (Intel Quad Core 2.4GHz, 4GiB)
Debug
Hello World!
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 195274 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 52963 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 52900 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 52885 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 52890 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 52934 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 70502 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 52904 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 76752 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 52398 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
Press any key to continue . . .
Release
Hello World!
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 231768 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 48735 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 33596 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 31932 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 31841 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 31821 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 31800 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 31770 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 31811 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
fft_bench v1.0
Freq. Magnitude
0 510
192 511
320 511
512 511
1024 point bit-reversal and butterfly run time = 31797 us
Operations timed using the system's high-resolution performance counter.
Timer frequency in ticks per second = 2394030000
Timer is accurate within 0 nanoseconds
Press any key to continue . . .
If your program uses classes, replacing them with structs might improve performance.
Theoretically struct is not instantiated the same way as a class and has direct references.
That's true, as a Struct is on the stack and a Class is in the heap. However, when passing them as a parameter to a method, a Struct will be passed by value, which is, it's copied to another instance, where a Class instance is passed by reference. By value is naturally slower due to the copying necessary.
Comments
That's almost enough to make me overlook the MicroSoft connection:)
@Jazzed, glad to hear we are breaking new ground here.
Thanks... I fixed the port validation bug.
There's one thing that I wondered about. On my system, I have one serial port and the FTDI driver but I see these items.
dev/ttyS0
dev/ttyS1
dev/ttyS2
dev/ttyS3
dev/ttyUSB0
Not sure why I see 4 ttySx.
I'll update the demo code, hopefully today, to spin off a new thread to monitor for serial IO. I built the GUI to handle textbox updates from a secondary thread. I imagine threading works the same in Linux.
If you had a good old fashioned mother board with serial ports on it they would be ttyS0 and ttyS1 at least.
Or plug a real serial port card in and they will be in use.
Not sure why they are still coming up for modern motherboards with no serial ports though.
Anyway, ttyS1-ttyS3 cause an error on the open event. I adjusted the code accordingly.
Edit: Here's the echo Prop code I used for testing.
If you can show me how to detect the various Parallax chips, Propeller, Basic Stamps, etc... I can do some detection for the uM-FPU and Various GPS modules.
I am including a new project to test a bit more in mono. This one is going to be a GUI not much is working yet, just getting the look and feel right now. I put
So that is what I realy want feedback for! *NUX systems should say "Unix", mac systems should display "MacOSX", and X-Box should say "XBox".
Also added some setting in the options menu. Let me know if it shows the available com ports as it did before. It works here in ms windows
I hope it works in mono....
I'm thinking you might be a little biased on this, Ross! :-)
Full Disclosure: I work for the Dark Side, so I'd love to see C# on the Prop! (But for now, I'll stick with Catalina/Spin/Asm for my real work!)
Bill
Jazzed. One correction, C# is a strongly typed language... there are no objects that are untyped. I think you might be referring to two objects where type is inferred and not exactly specified by the developer, Var and Dynamic. One is inferred at compile time based on usage and the other at runtime, but they are most definetly strongly typed.
Bill
I'm not sure how to detect a STAMP or Prop without having something running on the device. I know that STAMP has the ability to update the STAMP directive when the code is run. I'm not sure how that works and I'm not sure about the Prop. I am sure someone can let us know.
When I heard that Anders Hejlsberg (who designed Delphi as well as TurboPascal) had left Borland for Microsoft, I complained to my boss that now he would be making evil products. My boss' response was "at least they will be well-designed evil products."
In Anders' defense, it looks like he made a pretty good career move.
http://www.agaverobotics.com/serialportdemo.zip
If you click the send button with no data, "Hello World" is sent.
If need be I can wire up a more comprehensive data received handler.
Propeller test code.
That was funny! :-)
I have just been exercising a version of the fft_bench in C#, on a PC admittedly.
Turns out that using mono under C# the FFT is 60% slower than the C version. Now that is with a full up JIT compiler. I suspect it would be another 100 times slower if there were only a byte code interpreter on a small embedded system.
Strangely enough when I try to use the mono Ahead Of Time Compiler (AOT) it gets even slower!
All of which does not look good for C# on embedded systems.
Before I put up the results does anyone know any tricks to get C# programs with mono and the AOT to run faster?
Theoretically struct is not instantiated the same way as a class and has direct references.
Bill (wjsteele) might have more tricks.
As such the entire fft_bench is incorporated into a single class and are "static".
This version has no other structs or classes.
A struct does not use double indirection to methods and data members.
I can't remember all the differences just now.
Writing Faster Managed Code
Yes - just remove the "#".
Ross.
Oooh, he's sharp today...
Ha! Not so fast. Strangely enough results look a little better on my home PC. Also with mono on Debian.
Here the fft_bench in C runs in 81us and in C# it's 116us. That's only 43% slower. Again trying to use AOT slows it down.
Changing the only "class" to "struct" makes not even 1us difference.
I don't know what else can be done to speed this up. The idea of the thing is to, as far as possible, keep to the same code structure as the original Spin version. Same operators, types, loops, etc etc. This makes for a somewhat valid comparison between languages and CPUs.
To that end I tried to add only the minimum required by C# to get it to run.
Anyway the code is attached here for anyone who is interested.
If you use the "Native Image Generator Tool" NGen.exe,
Code is supposedly faster too, but I have never used it. It is in the .NET Framework SDK. , NOTE: SDK I'm not sure if it comes with just the .NET framework install.
Don't forget that over here in Linux land we don't have .NET Framework SDK or NGen.
However mono does have AOT, Ahead Of time Compilation. So,
1) Let monodevelop compile your code to a .exe
2) Run mono over it with some funky options that compile the bytecodes to native code and puts that into a .so library file.
3) Run the .exe with some more funky options to mono which causes it not to JIT.
Problem is that actually makes for slower run time!!!
Do the newer versions of Debain have kernal sources included with the disks/downloads or is it seperate now?
Perhaps that's why you are seeing slower execution times.
Bill
Linux box (AMD Sempron 2200, 1.5GiB)
Compiled in debug mode
Linux box (AMD Sempron 2200, 1.5GiB)
Compiled in release mode
Windows (Intel Quad Core 2.4GHz, 4GiB)
Debug
Release
That's true, as a Struct is on the stack and a Class is in the heap. However, when passing them as a parameter to a method, a Struct will be passed by value, which is, it's copied to another instance, where a Class instance is passed by reference. By value is naturally slower due to the copying necessary.
Both have advantages.
Bill