Why your website should be written in C, not PHP

Posted on by AJ Ianozi

It’s been awhile since I updated this blog, been pretty busy IRL. Just recently got back from a Longsword Course with ARMA, in Ohio, was very nice, and I learned a lot. I’ve also been playing the silver market recently; there’s a pretty nice blog that I follow. If you’re looking for an interesting perspective on precious metals, check this guy at Along the Watchtower; he seems to know his stuff.

Okay, back to the point of this post.

I have studied several scripting and programming languages; off the top of my head, I know Ada, C, C++, Fortran77, FORTH, Perl, PHP, Python, Java, and JavaScript. Which language do I prefer, though? C.

Now, for the record, just so you do know that there are plenty of sites written using something other than PHP. Any website ending in .cgi are usually written in a compiled language. I have came across some sites that are written in C++ before, and Deltapsi Studios, my good friend Stephan’s site, is written in C, with mysql support and everything.

Anyway, more and more people in today’s world are designing websites in PHP. After all, as one of my professors would say, “PHP is built for the web!” Maybe that’s why Facebook uses PHP. Addendum 08/27/11: Actually it seems like Facebook wrote their site in PHP, then used software to convert it into a complied language, since interpreted PHP wouldn’t be able to hold up the site.

C, on the other hand, I keep finding people consider it a low-level language that is only used by the hard-core programming. One of those “hard to learn” languages that take millions of lines of code to get things done.

Despite the above accusations, you will find that C is actually a very good language. It is an easy language to learn, and if programmed correctly, easy to understand, and by default, C is one of the fastest-executing programming languages out there, and when optimized, it can blow almost anything out of the water. Check the end of my switch() vs elseif benchmarks post. PHP took 8.169889 milliseconds to traverse my last test, whereas C took 0.01267 milliseconds.

Maybe you’re thinking, “Okay, PHP takes 8ms and C takes 0.01ms. A millisecond isn’t that long.” There are two points I should make. First, if you do the math between those two times, you find that C’s switch() executed almost 645 times faster than PHP. This in a matter of speaking, makes C about 64,500% faster than PHP! Now THAT, is a speed difference.

And even then, while a millisecond may not seem that much to you, if you’re having your web application serving hundreds or thousands or millions of requests, the speed difference will add up, and while the websites designed in C will be happily treading down the road, you’ll find your PHP-site stalling and lagging while the preprocessor parses for your people. For the virtual machine guys out there, if you want to get technical, ASP.NET or JSP should theoretically run faster than PHP.

Okay, so C is faster, C is more efficient, and I’m telling you that C is easier. “But Anthony!” you cry, “What about the sessions and the cookies and the hash map arrays and the typeless variables, and my strings, and HTML output, and…” Yes, yes. By this point, you realize that PHP was indeed designed for the web, hence it will have a ton of web-design libraries that are not in the Standard C Library. This means that if you want to use mysql, you will have to get the MySql Library and do your queries in C. If you want sessions, you will have to find a session system for C, or write your own.

Yes, you will have to have “type” your variables, that is, using “int iNumber = 3;” instead of “$Number = 3;” and you will loose those hashmap/linked list arrays that everyone seems to love so much, though if you look at that previous benchmark, you’d find the hashmaps in PHP executing pretty slowly as well. This is due to the slow nature of a hashmap, which is not in the scope of this entry, and just remember, in C, you can implement radix tables or something much, much, faster than hashmaps.

As for cookies, GET, and POST, it’s really not that hard. Below, you can read the get/post/cookie receiving that I used, in my C-web application, as well as the sessions system:

/*GET data*/
USEAGE_FLAG = getenv("QUERY_STRING");
if((USEAGE_FLAG != NULL) && *USEAGE_FLAG)
{
  GET_STR = mystr_strcreate(USEAGE_FLAG);
  GET = HTTP_parse(GET_STR->str, GET_STR->len+1); /*Parse the GET thing, store it in GET*/
  if(!GET)
  {
    error("Unable to parse get data", 1);
  }
}
else
{
  GET_STR = NULL;
  GET = NULL;
}

/*POST data*/
USEAGE_FLAG = getenv("CONTENT_LENGTH");
if((USEAGE_FLAG != NULL))
{
  long len = mystr_stratoi(getenv("CONTENT_LENGTH"));
  POST_STR = mystr_create(len+1);
  if(fgets(POST_STR->str, len+1, stdin) == NULL)
  {
    error("Unable to read post data", 1);
  }
  POST_STR->len = len+1;
  if(purge(POST_STR->str, len))
    error("Invalid POST",1);
  POST = HTTP_parse(POST_STR->str, POST_STR->len+1); /*Parse the POST thing, store it*/
  if(!POST)
  {
    error("Unable to parse post data", 1);
  }
}
else
{
  POST_STR = NULL;
  POST = NULL;
}

/*Cookie data*/
USEAGE_FLAG = getenv("HTTP_COOKIE");
if(USEAGE_FLAG != NULL)
{
  if(purge(USEAGE_FLAG, COOKIE_SIZE))
    error("What did you do?!",1);
  COOKIE_STR = mystr_strcreate(getenv("HTTP_COOKIE"));
  COOKIE = HTTP_parse(COOKIE_STR->str, COOKIE_STR->len+1); /*Parse the cookie*/
  if(!COOKIE)
  {
    error("Unable to parse cookie", 1);
  }
}
else
{
  COOKIE_STR = NULL;
  COOKIE = NULL;
}

/*If there's a cookie, load in the session.  If not, create a new cookie/session*/
if (COOKIE) /*There is a cookie -- load the existing session*/
{
  tmpstr = HTTP_retrieve(COOKIE, "mosplue");
  if(tmpstr)/*This should work*/
  {
    mystr_strcpy(session_fname, "../../data/sessions/");
    mystr_strcat(session_fname, tmpstr);
    mystr_strcat(session_fname, ".bin");
    session_file = fopen(session_fname->str, "r");
    if(session_file) /*If we find the session*/
    {
      if(fread(&session, sizeof(session), 1, session_file) != 1)
      {
        error("Unable to load session", 1);
      }
      fclose(session_file);
      /*Is the player logged in?*/
      if(session.loggedin == 1)
      {
        if(loadplayer(&player, session.username)) /*Does the player still exist?*/
        { /*If not, we can't continue*/
          session.loggedin = 0; /*TODO: Make "session_login" and "session_logout"*/
          session_file = fopen(session_fname->str, "w"); /*We should already have this from earlier*/
          if(fwrite(&session, sizeof(session), 1, session_file) != 1) 
          {
            error("Problem with session; if you continue to encounter this, clear your cookies", 1);
          }
          fclose(session_file); 
          error("Your account cannot be found.  You can try logging in again, or make a new account.", 1);
        }
        else
        {
          page_type = PAGE_MAP;
        }
      }
      else
      {
        page_type = PAGE_LOGIN;
      }
    }
    else /*I guess our session died or something -- kill the old cookie*/
    {
      puts("Set-Cookie: mosplue=; expires=Thu, 01 Jan 1970 00:00:01 GMT");
      /*Player WILL NEED to login*/
      error("Invalid session", 1);
    }
  }
  else
  { /*Invalid cookie*/
    puts("Set-Cookie: mosplue=; expires=Thu, 01 Jan 1970 00:00:01 GMT");
    error("Invalid session", 1);
    return 0;
  }
}
else /*There is no cookie -- create a new session*/
{
  int randnum;
  struct string_t* the_hash = mystr_create(AVG_STR); /*To hold our md5*/

  /*Create the new session*/
  memset(&session, 0, sizeof(session));
  for(;;)
  {
    tmpstr = CORE_IntegerToString(rand(), 10);
    md5_hex_string(the_hash->str, tmpstr);
    the_hash->len = 32;
    free(tmpstr);
    mystr_strcpy(session_fname, "../../data/sessions/");
    mystr_cat(session_fname, the_hash);
    mystr_strcat(session_fname, ".bin");
    if (!file_exists(session_fname->str))
    { /*We found a free session!*/
      session_file = fopen(session_fname->str, "w");
      break;
    }
  }
}

There is a downfall, however in C, and that is how horrible it handles strings. After all, with the happy-go-lucky $mystring = “Hi everyone!”; how can you go wrong? In PHP, to concat a string, all you have to do is:

"Hi " . "Everyone!"

I believe. Everyone knows that C-strings are slow. Try to concat a string in C multiple times, and you’ll quickly find that it has to traverse the string in strlen() every single time strcat() is called. If String A and String B are 256 characters, and you strcat() them, when you try to concat the new string, it will be twice as slow. Strings are a mess in C. So what did I do? I wrote a new string library, that handles strings like Pascal does:

struct string_t
{
  size_t len, /*Size of string to '\0' */
         max; /*Size of the total string*/
  char* str;
};

What’s the point of the above structure? Those that know C will probably be going “OH!”, and for those who don’t… I’m storing the length of the string in my actual string. You’ll notice a HUGE increase in performance once strlen() can return the length with str->len instead of for(s=str;*s;++s); So now, I can do,

string_t* mystr = mystr_create(256); //Make a string that can hold 256 characters.
mystr_concat(mystr, "Hello World!");

Was that so hard?

“What about outputting text?” What about it? It is true that in PHP, you can do:

<p>The number is: <?php echo $number ?></p>

Or whatever it is you do, but in C, I can just do:

printf("<p>The number is: %d<p/>", number);

What I’m doing, is simply embedding the HTML into the c-code, instead of embedding the c-code into the HTML. (NOTE: Stephan, if you’re reading this, no, I do not actually use printf..)

So in short, anything written in PHP can be written in C (even if you don’t feel like writing the systems yourself, there’s a good chance you can find a libcgi worth using), and PHP is slow (very slow). Now, I can go over and discuss

Comments (& Webmentions coming soon)

  • D.J. de Jager on

    Do you use a special server based website or do you just embed the C within HTML?

    IIRC there is a MS Visual Web Developer which supports C. Thank you for sharing this with us and I look forward to learning C from you.

    Replies

    • D.J. de Jager on

      I was also wondering what would be the fastest between C and HTML or C and Javascript?

  • A.J. on

    Hi. To answer your first question, I use CGI with Apache to run my C-code. Basically, I have a program, let's call it index.cgi, on my website. When a user views that program, my server executes it, and the output of the program is sent to the user's browser. So technically, the HTML is embedded into my C code, similar to Perl.

    To your second question, the fastest would be HTML. Since the end-result is being sent to the user as raw text, without any additional processing. For dynamic data, C would be faster than most alternatives. As far as javascript, that would be the slowest, as it's a client-side language that's interpreted in the user's browser.

    Replies

    • Anonymous on

      Actually, JS would be the fastest just like HTML, since there is no processing whatsoever on the server. And JS can scale indefinitely, because the code is executed on each single browser of each single user, so even if the server has to handle, say, 10.000 requests per minute, the speed degradation will be limited since there is no additional processing to be done by the server other than serving static files.

    • Anonymous on

      The above obviously is only true for client-side js, not stuff like node.js

    • Anonymous on

      The above obviously is only true for client-side js, not stuff like node.js

    • A.J. on

      Though a 100pct javascript website is not a fantastic user experience in my honest opinion. I try to have as little to no javascript on my sites as possible.

  • Doug on

    Nice article Anthony,

    I first learned C then C++, Perl, Java, PHP (javascript of course) and Python. From 1998 to 2001 I used C. Then from 2002 to 2010 I started using these other languages for back end web sites and applications. Finally after 10 years of developing in these other languages I've gone back to C and as of late, I've also been using Objective-C.

    Replies

    • A.J. on

      Hi Doug, glad to see you've finally wrapped back around to C.

      I've dabbled with Obj-C before with the mac, but that was about it.

  • Anonymous on

    Hi,

    Although this web site is not running in C, or is it?

    Have you got any good examples of web sites running C based blogging systems?

    Replies

    • A.J. on

      This site uses blogger.com's content management system. I read that it was programmed in Java originally, but knowing Google, I'm willing to bet they've switched to C, C++, and Go for this website.

  • Anonymous on

    Here I am looking around for people using C for their Sites and came across this. Good read.

    Although I can use various languages, I always have a soft spot for C. Awesome language.

    Thinking of using C for my home server. I mentioned this to a few co-workers and they thought I am mad. I am surrounded by .NET developers, afterall.

    I am surprised no one has commented about using C# instead of PHP and C.

    Good read!

    Replies

    • A.J. on

      Glad to see another fellow C user! Hope you find/create a decent libcgi for yourself if you take that route. I'm not a fan of .NET for the same reason I'm not a fan of Java; something irks me about both OOP and virtual machines. Just more unnecessary layers of abstractions.

      I've been hosting about 4 websites sites on a 12-year-old server running Gentoo for the longest time without any problems. The single-core AMD Athlon and 512MiB of ram ran quite smoothly while it was used. Never had a need for PHP, JSP, or even C#.

  • Zonova on

    Hey Anthony, i just have a quick question. Or maybe it's not so quick, i guess it depends on how you respond :P But this is a quote from your post:

    "(NOTE: Stephan, if you're reading this, no, I do not actually use printf..)"

    I'm still really early in learning C, so printf is the only thing i know to display text. What's wrong with using it?

    Replies

    • A.J. on

      Using printf() is fine when you start out learning C, but once you start trying to create some serious code that needs to be fast, you're going to want to start changing the methods you use.

      If you want to display "Hello World!" or give the user their calculated age, go ahead and use printf().

      If you're going to be outputting hundreds of lines of HTML for your cgi application, you might want to use a faster method such as first using fputs(), then printing the number with a fast solution, then using more fputs().

  • emre kanca on

    Isn't spawning new processes slower each time a new page requested when it's tens per a second?(Even php-with-cache)

    Or is there any (open) solution available to sort it out?

    Guess not!

    I would like to program in c too but over a year could not find right c solution unless writing my own environment from server to c servlets or what ever it could be.

    So any idea else?

    Replies

  • Anonymous on

    Hi Anthony, what web server would you use for the best performance?

    Replies

  • Anonymous on

    "... as PHP is written entirely in C." http://php.net/get-involved.php

    Misleading blog though.

    Replies

  • Omega on

    Hey Anthony,

    I run a SaaS company, and we use C in the backend all the time.

    However we use Python + C to strike a good balance between both worlds. Python and C work really well together as I'm sure you know.

    However when dealing with trivial details (routing requests, parsing posts, web stuff), Python can handle at speed anything that's thrown at it. And for the slow parts of the code (stats, financial projections), we rely on C to deliver the results in real time.

    When building applications in the real world, programmer speed is important, but application speed can't be forgotten.

    Replies