Why Julia is so much slower than Python? Invitation to Euler Project

BTW:

julia> factorial_digit_sum(n::Int64) = n |> big |> factorial |> digits |> sum

julia> @benchmark factorial_digit_sum(100)
BenchmarkTools.Trial: 
  memory estimate:  30.80 KiB
  allocs estimate:  1415
  --------------
  minimum time:     44.063 μs (0.00% GC)
  median time:      49.813 μs (0.00% GC)
  mean time:        98.234 μs (31.32% GC)
  maximum time:     117.051 ms (74.85% GC)
  --------------
  samples:          10000
  evals/sample:     1

A bit of type piracy, and then:

julia> Base.digits(b::BigInt) = [c - '0' for c in string(b)]

julia> @benchmark factorial_digit_sum(100)
BenchmarkTools.Trial: 
  memory estimate:  1.86 KiB
  allocs estimate:  14
  --------------
  minimum time:     1.659 μs (0.00% GC)
  median time:      1.925 μs (0.00% GC)
  mean time:        2.447 μs (7.45% GC)
  maximum time:     1.362 ms (35.47% GC)
  --------------
  samples:          10000
  evals/sample:     10
1 Like

Calling out and attacking people like this is not appropriate and is a violation of Julia’s community standards. Moreover this thread does not seem particularly constructive, especially since it lacks actual code to discuss. Accordingly, I have unlisted it and it will be locked if it doesn’t take a turn for the better.

2 Likes

So, it should be added to Julia 1.6.

Great! Then even with a suboptimal method for digits, we’re back to “how come julia is so blazing fast?”, which there are plenty of blog posts, press releases, and manual pages about.

There’s a relevant issue here: https://github.com/JuliaLang/julia/issues/27620

2 Likes

So, it was noted more than two years ago. Moreover, the solution was suggested at the same time. This proves that this thread was necessary to move it from the dead point. :slight_smile:

The remaining question is “Will it be enough?” Because it is so easy just to unlist the thread that annoys you and forget about the issue for another two years. :slight_smile:

This thread was unlisted because of your toxic behavior, not because you called out a performance issue. If you had not edited your top post to attack a set of people here, then it would still be listed. Feel free to contribute to the linked issue in a constructive manner. Since there is an apparent solution here, all it takes is for someone who cares to address this issue to make a pull request.

The answer to “Will it be enough?” is a question for you: will you care enough to take the effort to make a pull request and improve this?

1 Like

So, my pointing to the useless and trolling posts is a toxic behavior but the trolling posts of the mentioned users are not. Nice. Have you read all the thread? By the way, I am older than any of you and do not want to be treated like that.

You just does not like to accept any unpleasant facts and try to hide them from the outer view instead of addressing them.

@xiaodai’s posts were borderline, but everything else is fine and not only civil, but actively helpful and constructive. That you read polite, constructive feedback as toxic may say more about you than about the feedback. The edits you made to your top post, on the other hand, are very much over the line. Perhaps you thought that kind of behavior was ok. I’m telling you, unequivocally, that it is not: we do not do that kind of thing around here. Do not attack people like that.

The only unpleasant fact about Julia that’s been pointed out in this thread is fairly trivial: the digits(::BigInt) method should be optimized. Moreover, there was already an open (public) issue for this precise performance problem, so we haven’t even learned anything new. At some point, someone will care enough about this optimization opportunity and fix it. That could be you, if you care to be constructive.

The reason I have unlisted this thread is because your top post is absolutely not what people should be exposed to when they visit the Julia forums. If you want to edit it to remove your toxic commentary, I will relist it and split the follow-on conversation into a separate (unlisted) thread.

2 Likes

@gevis I would like to apologise if I have caused offense. Your edits to ur top post now reads more like a serious discussion. However, I was under the impression that trolling has occured according to the following definition:

What Is Trolling ? Trolling is defined as creating discord on the Internet by starting quarrels or upsetting people by posting inflammatory or off-topic messages in an online community. Basically, a social media troll is someone who purposely says something controversial in order to get a rise out of other users.

There were a couple of leaps of logic that I thought were clearly designed to incite. I also apologise if I read those wrong. But it made me feel like I would be wasting my efforts if I did try to come up with a constructive and proper response.

I have brought up issues with Julia in my blogpots and on twitter, so I won’t simply defend Julia if it’s slow just because I use it.

1 Like

@gevis

(in addition to what @StefanKarpinski and @xiaodai have said)

The posts by the “toxic” users you mentioned (including me) are mostly just humoristic. Not every discussion is supposed to be strictly-technical, so you will always see the posts you call “useless”, whose basic intention is most usually just to entertain other Discource users and to engage the further discussion.

Sometimes you have to imagine the faces of other participants in an online discussion. If you have seen a grin on my face writing a humoristic remark, I highly doubt you’d think I had toxic intentions.

Obviously, if you don’t like such posts (not just in this thread, but in any other), you can just ignore them. It’s like not laughing at somebody else’s joke, nobody forbids you from doing that.

But I’m still offended by you giving me only the third place on that list. :confused:

I actually do not think that it is worth anybody’s time to tinker with this thread (read every post, decide to which thread it should belong, if necessary edit, split to two threads, relist, etc.) if the problem with digits(::BigInt) will be solved in Julia 1.6, especially when you have already acknowledged its existence.

Another reason to not relist this thread is that it violates the Project Euler rules. So, let’s leave it as it is and use our time more effectively.

May the fact that, in this respect, you are on the top for this and previous my thread cheer you up a bit? :slight_smile:

Well, I accept the apologies.

Тo end the discussion, I would like to share some additional thoughts and, as this threads has already been unlisted and not seen to the general public, I hope that your reaction to them will not be so defensive.

  1. First of all, I think that measuring only the execution time of a function for an interpreted language and stating on this basis that it "blazingly fast " is not fair. Especially because the most common case for interpreted language usage is running the program only once. And for this case, measuring the total running time (compilation + execution) is more appropriate.

  2. If the function is in the core of the language, by which I mean that it is present even before you load any additional package, the general user have the right to expect that it executes at least as fast as any of his own its realizations.

Returning to our
factorial_digit_sum(n::Int64) = n |> big |> factorial |> digits |> sum
with current realization of the digit() function, for n=1000, it runs 1.73 seconds (with compilation, the BenchmarkTools give here 4.3 milliseconds), whereas the corresponding Python realization executes in just 2.4 milliseconds (on my old computer), whereas with the realization of the digit(::BigInt) function, proposed here by DNF, the BenchmarkTools give me 78.2 microseconds (execution only), the total execution time (compilation + execution) is 166 milliseconds though (anyway, much slower than that of Python).

Julia is a nice programming language with many interesting and attractive features. It even may be preffered to other programming languages in some user cases. But let’s estimate its performance (and other shortcomings currently present) realistically. This approach at least can help to eliminate some of its current shortcomings.

It’s certainly not a release-blocking problem. The issue will be fixed if someone puts the time and effort in to fix it.

1 Like

Julia is a jit-compiled language, not interpreted. Including compilation time makes little sense; if you only care about single-use interactive performance, you cannot tell the difference between 100 ms and 0 ns, anyway. The runtime becomes interesting when you run a piece of code many times, in which case compilation time should not be included.

Nevertheless, there is something wrong with your timing. On my computer with the current digits, including compilation:

julia> @time factorial_digit_sum(1000)
  0.005894 seconds (23.10 k allocations: 1.709 MiB)

There is nothing special about ‘built-in’ functions, and in fact it is quite expected that you can write your own code that is faster than the built-in functions, because you can exploit special properties of your problem that only you know about; or you can speed things up by trading off numerical accuracy or disregarding edge cases. For example, you could easily write your own sum function that outperforms the ‘built-in’ one.

1 Like

On my old computer with 2-core Athlon 5000 processor, the same code outputs

0.174636 seconds (207.41 k allocations: 11.256 MiB)

when run for the second time (as a script). However, when run at the first time after rebooting the computer, it outputs 1.73 seconds.

What’s the Julia version?

Julia 1.0.3 on this computer.

I don’t have that version, mine is on 1.5. Perhaps compiler improvements, though the difference is starker than expected.

With Julia 1.4.0 on a more powerful computer with 4-core Phenom II 945 processor, the same script runs 0.05699 seconds on the first run and about 0.003789 seconds on the second and subsequent runs.