C is NOT significantly more efficient than C Sharp

S

spinoza1111

This is C code, which calculates the factorial of 19 1000000 times
both iteratively and recursively:

#include <stdio.h>
#include <time.h>

long long factorial(long long N)
{
long long nFactorialRecursive;
long long nFactorialIterative;
long long Nwork;
if (N <= 2) return N;
for ( nFactorialIterative = 1, Nwork = N;
Nwork > 1;
Nwork-- )
nFactorialIterative *= Nwork;
nFactorialRecursive = N * factorial(N-1);
if (nFactorialRecursive != nFactorialIterative)
printf("The iterative factorial of %I64d is %I64d but its recursive
factorial is %I64d\n",
N,
nFactorialIterative,
nFactorialRecursive);
return nFactorialRecursive;
}

int main(void)
{
long long N;
long long Nfactorial;
double dif;
long long i;
long long K;
time_t start;
time_t end;
N = 19;
K = 1000000;
time (&start);
for (i = 0; i < K; i++)
Nfactorial = factorial(N);
time (&end);
dif = difftime (end,start);
printf("The factorial of %I64d is %I64d: %.2f seconds to calculate
%I64d times\n",
N, Nfactorial, dif, K);
return 0;
}

Here is the equivalent C Sharp code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class findStudentNames : Form
{
private RichTextBox RTBinput = null;
private RichTextBox RTBoutput = null;

private const double WIDTH_TOLERANCE = .75;
private const double HEIGHT_TOLERANCE = .75;
private const double TEXTBOX_RATIO = .85;

private struct TYPname
{
private string STRfirst;
private string STRchinese;
private string STRpatronym;
public TYPname(string strFirst,
string strChinese,
string strPatronym)
{
STRfirst = strFirst.Trim();
STRchinese = strChinese.Trim();
STRpatronym = strPatronym.Trim();
}
public string toString()
{
return STRfirst + " " +
(STRchinese == ""
?
""
:
"(" + STRchinese + ")") + " " +
STRpatronym;
}
}

public findStudentNames()
{
InitializeComponent();
}

private void cmdFind_Click(object objSender,
EventArgs objEventArgs)
{
findNames_();
}

private void Form1_Load(object objSender,
EventArgs objEventArgs)
{
customizeForm_();
}

private void customizeForm_()
{
try
{
this.Text = "findStudentNames";
this.Show();
this.Opacity = .5;
this.Refresh();
this.FormBorderStyle = FormBorderStyle.Fixed3D;
this.MinimizeBox = false;
this.MaximizeBox = false;
this.Width = (int)

(windowsUtilities.windowsUtilities.screenWidth()
*
WIDTH_TOLERANCE);
this.Height = (int)

(windowsUtilities.windowsUtilities.screenHeight()
*
HEIGHT_TOLERANCE);
int intGrid =
windowsUtilities.windowsUtilities.Grid;
int intGrid2 = intGrid << 1;
int intAvailable = 0;
this.Controls.Add
(RTBinput =
windowsUtilities.windowsUtilities.mkRichTextBox
("",
intGrid,
intGrid,
(int)
((intAvailable = ClientSize.Width - intGrid2)
*
TEXTBOX_RATIO),
ClientSize.Height
-
intGrid * 3
-

windowsUtilities.windowsUtilities.defaultButtonHeight()));
RTBinput.Font = new Font(FontFamily.GenericMonospace,
10);
RTBinput.ScrollBars = RichTextBoxScrollBars.Vertical;
RTBinput.Multiline = true;
RTBinput.WordWrap = false;
this.Controls.Add
(RTBoutput =
windowsUtilities.windowsUtilities.mkRichTextBox
("",
RTBinput.Right,
RTBinput.Top,
intAvailable - RTBinput.Width,
RTBinput.Height));
RTBoutput.Font = new Font(FontFamily.GenericMonospace,
10);
RTBoutput.ScrollBars = RichTextBoxScrollBars.None;
RTBoutput.Multiline = true;
RTBoutput.ReadOnly = true;
RTBoutput.WordWrap = false;
Button cmdNew = null;
this.Controls.Add
(cmdNew =
windowsUtilities.windowsUtilities.mkButton
("Find",
intGrid,
RTBinput.Bottom + intGrid));
cmdNew.Click += cmdFind_Click;
this.CenterToScreen();
this.Opacity = 1;
this.Refresh();
}
catch (Exception objException)
{
throw new Exception("Can't customize form",
objException);
}
}

private void findNames_()
{
int intIndex1 = 0;
TYPname usrName = new TYPname("", "", "");
string strName = "";
int intNameLengthInSource = 0;
while (find__locateNameNumberPrefix_(RTBinput.Text,
ref intIndex1))
{
if (find__locateName_(RTBinput.Text,
ref intIndex1,
ref usrName,
ref intNameLengthInSource)
&&
RTBoutput.Text.IndexOf
(strName = usrName.toString())
==
-1)
{
RTBoutput.Text +=
(RTBoutput.Text == ""
?
""
:
Environment.NewLine) +
strName;
RTBinput.SelectionStart = intIndex1;
RTBinput.SelectionLength =
intNameLengthInSource;
RTBinput.SelectionColor = Color.Red;
RTBinput.SelectionFont = new
Font(RTBinput.Font, FontStyle.Bold);
RTBoutput.Refresh();
}
}
}

private static bool find__locateName_
(string strTextNext,
ref int intIndex,
ref TYPname usrName,
ref int intNameLengthInSource)
{
intNameLengthInSource = 0;
if (find__locateName__isName_(strTextNext.Substring
(intIndex),
ref usrName,
ref intNameLengthInSource))
return true;
return false;
}

//
// name := ALPHA_STRING
// [ "(" (ALPHA_STRING [ " " ALPHA_STRING ] )* ")" ]
// ALPHA_STRING
//
private static bool find__locateName__isName_
(string strCandidate,
ref TYPname usrName,
ref int intLength)
{
intLength = 0;
string strFirst = "";
string strChinese = "";
string strPatronym = "";
int intIndex1 = 0;
find__locateName__isName__skipBlanks_
(strCandidate, ref intIndex1);
return find__locateName__isName__alphaString_
(strCandidate,
ref intLength,
ref strFirst)
&&
find__locateName__isName__chinese_
(strCandidate,
ref intLength,
ref strChinese)
&&
find__locateName__isName__alphaString_
(strCandidate,
ref intLength,
ref strPatronym);
}

private static bool find__locateName__isName__alphaString_
(string strCandidate,
ref int intIndex,
ref string strValue)
{
int intIndex1 = intIndex;
intIndex = utilities.utilities.verify
(strCandidate,
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz",
intIndex);
strValue = strCandidate.Substring
(intIndex1, intIndex - intIndex1);
return strValue != "";
}

private static bool find__locateName__isName__chinese_
(string strCandidate,
ref int intIndex,
ref string strValue)
{
strValue = "";
find__locateName__isName__skipBlanks_
(strCandidate, ref intIndex);
if (intIndex >= strCandidate.Length
||
strCandidate[intIndex++] != '(') return false;
int intIndex1 = 0;
while (intIndex >= strCandidate.Length
||
strCandidate[intIndex] != ')')
{
strValue =
strValue +
(strValue != "" ? " " : "") +
(strCandidate + " ").Substring
(intIndex,
(intIndex1
=
strCandidate.IndexOf(' ', intIndex))
-
intIndex);
intIndex = intIndex1;
find__locateName__isName__skipBlanks_
(strCandidate, ref intIndex);
}
return strValue != "";
}

private static void find__locateName__isName__skipBlanks_
(string strCandidate,
ref int intIndex)
{
for (;
intIndex < strCandidate.Length
&&
strCandidate[intIndex] == ' ';
intIndex++);
}

private static bool find__locateNameNumberPrefix_
(string strText, ref int intIndex)
{
intIndex = utilities.utilities.verify
(strText + "0", "", intIndex, true)
-
1;
return intIndex < strText.Length;
}

}
}

The C code is only ten percent faster, and this is explained by set up
time for the threaded-code environment (and the benefits of safety and
platform independence) in the C Sharp code.

It is an Urban Legend, of course, that C Sharp is interpreted whereas
C is not. This is incorrect, since if it were, the execution time of
the C Sharp code would be in this particular example several orders of
magnitude larger owing to the amount of recursion and looping in the
example.

In the C Sharp environment, bytecodes cause control to be transferred
to handlers. There is NO parsing, scanning or analysis needed when
instructions are revisited.

Like the American constitution, the code is "a machine that would run
of itself".

And like our Constitution at its best, while it runs it provides a
certain level of assurance that nasty things won't happen, as opposed
let us say to the British constitution, which is constantly
interpretable by Parliament. There's no assurance, for example, that a
Mad King Charles won't in the near future refuse Royal Assent to some
measure.

A basic barbarism and regression, which is also evident in the
abominable treatment of Mr Wang Yip in the Void Main thread, makes
people want to "control" things.
 
B

bartc

Here is the equivalent C Sharp code:
windowsUtilities.windowsUtilities.defaultButtonHeight()));

Is this actual C# code? Why do you have to write windowsUtilities twice?
The C code is only ten percent faster, and this is explained by set up
time for the threaded-code environment (and the benefits of safety and
platform independence) in the C Sharp code.

The C# appears to be an utterly different program; the first rule about
benchmarking language implementations is to compare like with like.
It is an Urban Legend, of course, that C Sharp is interpreted whereas
C is not. This is incorrect, since if it were, the execution time of
the C Sharp code would be in this particular example several orders of
magnitude larger owing to the amount of recursion and looping in the
example.

I doubt whether recursion and looping enters into it. Typical bytecode
interpreters are one or two magnitudes slower than C, not several. C# uses a
more sophisticated scheme, last time I looked. It is somewhat slower than C
but is used in areas where this is not relevant.
 
F

Flash Gordon

bartc said:
The C# appears to be an utterly different program; the first rule about
benchmarking language implementations is to compare like with like.

Don't you realise that it is your fault for not making the obvious
substitution of a program which actually calculates the factorial for
one which does something completely different?

I doubt whether recursion and looping enters into it. Typical bytecode
interpreters are one or two magnitudes slower than C, not several. C#
uses a more sophisticated scheme, last time I looked. It is somewhat
slower than C but is used in areas where this is not relevant.

It's far more interesting to see the difference when compiling the same
program in the same language to both byte code and native code. Then you
get to see the overhead of the byte code interpreter. Or to compare the
same program in different languages both compiled to byte code (or
native code) so you can see the difference in performance due to the
natural way for programming in the language.
 
F

Flash Gordon

bartc said:
The C# appears to be an utterly different program; the first rule about
benchmarking language implementations is to compare like with like.

Don't you realise that it is your fault for not making the obvious
substitution of a program which actually calculates the factorial for
one which does something completely different?

I doubt whether recursion and looping enters into it. Typical bytecode
interpreters are one or two magnitudes slower than C, not several. C#
uses a more sophisticated scheme, last time I looked. It is somewhat
slower than C but is used in areas where this is not relevant.

It's far more interesting to see the difference when compiling the same
program in the same language to both byte code and native code. Then you
get to see the overhead of the byte code interpreter. Or to compare the
same program in different languages both compiled to byte code (or
native code) so you can see the difference in performance due to the
natural way for programming in the language.
 
B

bartc

Flash Gordon said:
bartc wrote:

It's far more interesting to see the difference when compiling the same
program in the same language to both byte code and native code. Then you
get to see the overhead of the byte code interpreter.

That would be interesting to see, but bytecode tends to be used for
different languages where it's more apt. Comparing to C is then harder
because it's tempting to use higher level features of the other language
(although this might be exactly what makes it viable to interpret rather
than compile).

(This is pretty much what I'm doing at the moment. I have plain, interpreted
(not JIT-compiled) bytecode, which when benchmarked against C using only
low-level code on a PC, is typically 6x slower when static typing is
introduced (otherwise nearer 10x). When there is lots of data memory
involved however, that 6x can reduce to 2x as slow, so simply using main
memory is as big an overhead as using bytecode!)
 
S

spinoza1111

Is this actual C# code? Why do you have to write windowsUtilities twice?


The C# appears to be an utterly different program; the first rule about
benchmarking language implementations is to compare like with like.


I doubt whether recursion and looping enters into it. Typical bytecode
interpreters are one or two magnitudes slower than C, not several. C# uses a
more sophisticated scheme, last time I looked. It is somewhat slower than C
but is used in areas where this is not relevant.

The post was made in error and then deleted. See its replacement at
http://groups.google.com.hk/group/comp.lang.c/browse_thread/thread/4cf78a2afa73b77a?hl=en#.
 
S

spinoza1111

Don't you realise that it is your fault for not making the obvious
substitution of a program which actually calculates the factorial for
one which does something completely different?



It's far more interesting to see the difference when compiling the same
program in the same language to both byte code and native code. Then you
get to see the overhead of the byte code interpreter. Or to compare the
same program in different languages both compiled to byte code (or
native code) so you can see the difference in performance due to the
natural way for programming in the language.

As I have said with respect to Heathfield's malicious lie concerning
my presence at comp.risks, a pure error indicates nothing about
credibility esp when retracted; I deleted the post.

Therefore, Flashie, I'm not going to read your reply.

The corrected post is now at
http://groups.google.com.hk/group/comp.lang.c/browse_thread/thread/4cf78a2afa73b77a?hl=en#.

Please direct all replies there and I will answer them, Flasho.
 
J

jacob navia

I transformed that program a bit. It calculates now factorial of 20, and
it does that 10 million times.

Note that the difftime function is not accurate. I used the utility "timethis".
Machine: Intel i7 (8 cores) with 12GB RAM

The results are:
-------------------------------------------------------------------------------------
D:\temp>csc /o tfact.cs C# Optimizations ON
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
D:\temp>timethis tfact
TimeThis : Command Line : tfact
TimeThis : Start Time : Sun Dec 27 18:33:53 2009

The factorial of 20 is 2432902008176640000: 00:00:03.7460000 seconds to calculate 10000000 times

TimeThis : Command Line : tfact
TimeThis : Start Time : Sun Dec 27 18:33:53 2009
TimeThis : End Time : Sun Dec 27 18:33:57 2009
TimeThis : Elapsed Time : 00:00:03.804
---------------------------------------------------------------------------------------
D:\temp>cl -Ox tfact.c C optimizations ON
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
tfact.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
/out:tfact.exe
tfact.obj
D:\temp>timethis tfact
TimeThis : Command Line : tfact
TimeThis : Start Time : Sun Dec 27 18:34:10 2009

The factorial of 20 is 2432902008176640000: 3.00 seconds to calculate 10000000 times

TimeThis : Command Line : tfact
TimeThis : Start Time : Sun Dec 27 18:34:10 2009
TimeThis : End Time : Sun Dec 27 18:34:13 2009
TimeThis : Elapsed Time : 00:00:02.666
D:\temp>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top