Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
[flagged] Yes, PHP is faster than C# (withinboredom.info)
15 points by withinboredom on March 16, 2022 | hide | past | favorite | 30 comments


This is a pretty worthless comparison.

* The C# version invokes EndOfStream up to 4096 times for every 1 call to feof in PHP version.

* The C# version opens the file in text mode (and thus does UTF-8 decoding) whereas the PHP version opens the file in binary mode.


The previous post on this blog makes another worthless comparison, this time based on lines of code:

https://withinboredom.info/blog/2022/03/16/my-favorite-langu...

> Like, look at this Merge Sort in C# [1] (130 lines) and then look at it in PHP (31 lines) [2]. You can’t beat that kind of productivity, not to mention in PHP, you can even mix data types (like ints and floats) where in the C# version, it’d be much more difficult.

[1] https://github.com/TheAlgorithms/C-Sharp/blob/master/Algorit...

[2] https://www.w3resource.com/php-exercises/searching-and-sorti...

The C# version is the first Google result for "c# merge sort". But a later result is from w3resource.com, which where the PHP code came from. That C# code is only 55 lines and could easily be shorter by replacing loops with standard library calls:

https://www.w3resource.com/csharp-exercises/searching-and-so...

Also, both versions of the code from w3resources.com are trash -- they use an O(N) step to remove an element from the front of the array (array_slice in PHP and List.Remove in C#), which makes them O(N^2 log N), which is even worse than a naive selection sort or bubble sort.


The C# version only makes a syscall if the buffer is empty: https://github.com/dotnet/runtime/blob/1ba0394d71a4ea6bee7f6...

To read in binary, you open with 'rb' and not just 'r'


Syscalls are not the only consumer of wall clock time, which is what was measured.

> To read in binary, you open with 'rb' and not just 'r'.

No. "The default translation mode is 'b'." [1] And even in 't' mode, it's still reading bytes in PHP vs UCS-2 characters in C#.

[1] https://www.php.net/manual/en/function.fopen.php


but it makes function calls, it's not neglectable as it's called as many time as the bytes the file has


That’s the api provided, and part of the point. The other option is to read the buffer directly, but it isn’t exposed to the programmer.


the overload is right below it

  int StreamReader.Read()
  int StreamReader.Read(char[] buffer, int index, int count)
https://github.com/dotnet/runtime/blob/1ba0394d71a4ea6bee7f6...


You just need to do File.OpenRead instead of OpenText to get a FileStream, then you can read the buffer


this is very naive reimplentation of the C# version. I managed to reduce the runtime of the same file from 5.7 seconds to just 800ms

    using var file = File.OpenRead("file.bin");
    var counter = 0;
    var sw = Stopwatch.StartNew();
    var buf = new byte[4096];
    while (file.Read(buf,0,buf.Length) > 0)
    {
        foreach (var t in buf)
        {
            if (t == '1')
            {
                counter++;
            }
        }
    }

    sw.Stop();
    Console.WriteLine($"Counted {counter:N0} 1s in {sw.Elapsed.TotalMilliseconds:N4} milliseconds");


This code has a bug that can cause the count to be overreported. The last `file.Read` may only partially fill the buffer, but this code will look for 1s in the entire buffer.

(This bug won't affect the performance comparison, but I was just reminded of how error prone these kinds APIs can be vs the PHP/Python route of having the library function just allocate a new buffer each time.)


Would something like this help? (No of course I haven't compiled it.)

    int len;
    while ((len=file.Read(buf,0,buf.Length)) > 0) {
        for (int i=0; i<len; i++_) {
            if (buf[i] == '1') {
                counter++;
            }
        }
    }


If you know the file isn’t too large, there also is File.ReadAllBytes (https://docs.microsoft.com/en-us/dotnet/api/system.io.file.r...)

My C# is very rusty (no pun intended) but I would guess the core of the program could be something like

  File.ReadAllBytes("file.bin").Where(x => x == '1').Count()
And nitpick: the code you gave has a bug. file.Read can return less than 4096. If so, you should only loop over the part of the buffer it filled.


C# isn't the unholy incantations of unmaintainable cargo cult development. I don't care if its faster, I care if I have to weep for hours prior rewriting ungodly spaghetti. I've written code in many languages professionally, in the hierarchy of fuckery I've seen done in order to write code php is worse than perl, which is worse than js, which is worse than sucking on the teets of the chthonic elder gods. I would rather eat a hefty bowl of my own vomit while walking across a mile of broken glass before having to maintain anything written in php.



That's a very convincing demonstration... that the author doesn't understand how to write moderately efficient C#


Ya, maybe. But it's easier to develop bug free code on C#. Speed has its advantages but it's not the only criteria used to decide what language to use.


I respectfully disagree. Modern PHP is an excellent language to work in, despite all the gripes old timers have from the old version 4/5 days. You can write top shelf Object oriented patterns, with first class dependency injection support. Type hinting. Built in Interface support. A really nice module/ import system. Composer is a fantastic dependency manger, and automatically gives you a magical class autoloader script with a small amount of configuration. Also PHP 8 includes all the modern conveniences you’d expect, like arrow function notation for closures, Enums, the Null Coalescing Operator, need I go on? :)


You have a point. It's been years since I worked on both so things might have changed. I'm thinking of a time when you not only needed to know PHP but you also had to know the work arounds of known issues with the language. PHP is very popular so maybe all that stuff has gone away or reduced greatly.


I respect your response. To be fair, I’m biased because I’ve only been doing web development for about 5-6 years. And I just so happened to land a job at a company firmly entrenched in the PHP world. So I came into the game late. I missed all the nonsense, and reasons a lot of more experienced web developers hate PHP. But working in Laravel is fantastic, and I equate it to the same reasons many developers love working in Ruby on Rails. The framework gives you high level design patterns out of the box, and the ecosystem surrounding it is incredible.


> But it's easier to develop bug free code on C#.

Wow, that's a claim I've never seen before. What's it based on? (As an example, I'm wondering if you may not be aware that there are several static analysis tools for PHP.)


I'm going by an article I read a few years ago.

https://cacm.acm.org/magazines/2017/10/221326-a-large-scale-...

Also, I used to program in both and known issues within the PHP language would make my development so much harder. But it's been pointed out to me that PHP has improved over the years so it might not be as difficult as before.


Isn’t this reading the file in 4K chunks in the php version and byte by byte in the C# version? If so they are completely different programs. The C# program would have 4096 times the number of method calls to Read()?

Edit: To clarify it’s buffered in C# too but the difference is that it’s fetched one byte at a time via a method call per byte. Not an I/O call per byte (then the difference would have been much larger of course).


This is addressed in the article:

> “But Rob,” I hear you say, “they’re not reading it byte-by-byte in the PHP version!” and I’d reply with, “but we’re not reading it byte-by-byte in the C# version either!”

C# also reads in 4K chunks: https://github.com/dotnet/runtime/blob/1ba0394d71a4ea6bee7f6...


That just means there aren’t 4K times as many file read ops.

The read() calls (which most of the time just increment the index into the buffer and returns what’s there) are still made.

The usual way of doing what he’s trying to do will look exactly the same in C# as in his php version, with explicit buffering.


You can follow the link to the underlying C# library where it is reading it in 4kb chunks as well. PHP doesn’t buffer for you, so if you want to read a file one byte (to your peril) at a time, you can. It’ll be as fast as the async version of the C# implementation, but still slower than reading buffered.


Both of these programs will make the same I/O calls but the total number of method invocations will differ by a factor 4096 unless I’m mistaken (it’s late). Those are cheap, but not free.


Does anyone know if PHP's "substr_count" function uses SIMD? I did a write-up on this: https://dev.to/goaty92/in-response-to-yes-php-is-faster-than... where I implemented a counter with SIMD and get a 10-fold performance increase.


Here's the latest optimization to that func: https://github.com/php/php-src/commit/085b360abb622abc18b955...

In the latest addendum on the blog post, I ended up removing the counting of 1s.


1.that's not pretty good C# code. Though i can't comment on the quality of PHP

2.Programming languages are more then their syntax, they are entire ecosystems. 99% of the time its not the syntax/features/paradigms that make you move fast its the libraries


What's the point?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: