# Julia slower than Python to sort and reverse a list of integers

**URL:** <https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453>\
**Category:** Performance\
**Created:** [April 13, 2023, 10:45pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453 "2023-04-13T22:45:57Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![lucasmsoares96](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucasmsoares96/32/38743_2.png) [@lucasmsoares96](https://discourse.julialang.org/u/lucasmsoares96)\
**Post date:** [April 13, 2023, 10:45pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/1 "2023-04-13T22:45:57Z")

</div>

My goal is to compare Julia’s performance against other languages like Python, Scala and Rust to perform some simple tasks. My first task was to sort an array of 999999 integers read from a text file.

The code below runs at a similar time in Python and in julia

```python
import time

st = time.time()
f = open("random_numbers.txt", "r")
lines = f.readlines()
numbers = list(map(lambda x : int(x.strip()), lines))
numbers.sort()
numbers.reverse()
et = time.time()
elapsed_time = et - st
print('Execution time:', elapsed_time, 'seconds')

```

0.4491417407989502 seconds

```julia
import Base: parse

parse(x) = y -> parse(x,y)
@time begin
    lines = readlines("random_numbers.txt")
    (lines .|> parse(Int64)) |> sort |> reverse
end;

```

1.122733 seconds

But when I add a print in the codes there is a significant performance discrepancy between Julia and Python

```python
import time

st = time.time()
f = open("random_numbers.txt", "r")
lines = f.readlines()
numbers = list(map(lambda x : int(x.strip()), lines))
numbers.sort()
numbers.reverse()
for n in numbers:
    print(n)
f.close() 
et = time.time()
elapsed_time = et - st
print('Execution time:', elapsed_time, 'seconds')

```

4.248031377792358 seconds

```julia
import Base: parse

parse(x) = y -> parse(x,y)
@time begin
    const lines = readlines("random_numbers.txt")
    (lines .|> parse(Int64)) |> sort |> reverse .|> println
end;

```

10.152690 seconds

Any hints as to what could be causing this underperformance of the Julia?

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [April 13, 2023, 10:52pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/2 "2023-04-13T22:52:23Z")

</div>

Check out the [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/)

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 13, 2023, 10:56pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/3 "2023-04-13T22:56:22Z")

</div>

I can’t reproduce your timings. I get

```julia
  0.515662 seconds (4.16 M allocations: 125.246 MiB, 9.27% gc time, 15.40% compilation time)

```

for Julia, vs

```julia
Execution time: 0.7124240398406982 seconds

```

for Python. And I can halve the Julia runtime by simplifying the code to

```julia
@time let
    lines = readlines("random_numbers.txt")
    (lines .|> Base.Fix1(parse, Int64)) |> sort |> reverse
end

```

Now I get

```julia
  0.261280 seconds (2.00 M allocations: 86.157 MiB, 6.06% gc time)

```

For reference, my platform is

```julia
julia> versioninfo()
Julia Version 1.8.5
Commit 17cfb8e65ea (2023-01-08 06:45 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, haswell)
  Threads: 1 on 8 virtual cores

```

---

<div class="post-metadata">

**Author:** ![lucasmsoares96](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucasmsoares96/32/38743_2.png) [@lucasmsoares96](https://discourse.julialang.org/u/lucasmsoares96)\
**Post date:** [April 13, 2023, 11:03pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/4 "2023-04-13T23:03:43Z")

</div>

could you test the code version with println?

```julia
import Base: parse

parse(x) = y -> parse(x,y)
@time begin
    const lines = readlines("random_numbers.txt")
    (lines .|> parse(Int64)) |> sort |> reverse .|> println
end;

```

my platform is:

```plaintext
julia> versioninfo()
Julia Version 1.8.5
Commit 17cfb8e65ea (2023-01-08 06:45 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: 8 × Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, haswell)
  Threads: 4 on 8 virtual cores
Environment:
  JULIA_NUM_THREADS = 4

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 13, 2023, 11:10pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/5 "2023-04-13T23:10:40Z")

</div>

It’s all about 8 seconds for both Python and Julia, but I don’t know what you’re measuring at this point: reading from file? parsing? sorting? reversing? printing? This is getting all very confusing.

---

<div class="post-metadata">

**Author:** ![lucasmsoares96](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucasmsoares96/32/38743_2.png) [@lucasmsoares96](https://discourse.julialang.org/u/lucasmsoares96)\
**Post date:** [April 13, 2023, 11:25pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/6 "2023-04-13T23:25:06Z")

</div>

8 seconds for both? There must be something wrong with my environment. My Julia spends 10 seconds while python spends 4 seconds.

The biggest discrepancy happens when I add the `println` in Julia

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [April 13, 2023, 11:28pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/7 "2023-04-13T23:28:38Z")

</div>

Julia 1.9-rc2 `--startup-file=no`:  
16.069481 seconds (11.35 M allocations: 350.027 MiB, 1.09% gc time, 1.53% compilation time)

Python 3.10.8: Execution time: 5.241699695587158 seconds

I find this to be a practical benchmark that combines multiple functions in a realistic way, so the performance is worth evaluating.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [April 13, 2023, 11:34pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/8 "2023-04-13T23:34:30Z")

</div>

The Python one is sorting and reversing the list in place.

In Julia that’s

```julia
import Base: parse

parse(x) = y -> parse(x,y)
@time begin
    const lines = readlines("random_numbers.txt")
    rows = [parse(Int, l) for l in lines]
    sort!(rows)
    reverse!(rows)
    println.(rows)
end;

```

but it makes no difference

15.431943 seconds (10.21 M allocations: 309.901 MiB, 1.10% gc time, 0.85% compilation time)

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [April 13, 2023, 11:38pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/9 "2023-04-13T23:38:36Z")

</div>

I think it’s that Python buffers stdout by default and Julia doesn’t.

> <https://github.com/JuliaLang/julia/issues/43176>
>
> \<!--
> If you have a question please search or post to our Discourse site: https:…//discourse.julialang.org.
> We use the GitHub issue tracker for bug reports and feature requests only.
> 
> If you're submitting a bug report, be sure to include as much relevant information as
> possible, including a minimal reproducible example and the output of \`versioninfo()\`.
> If you're experiencing a problem with a particular package, open an issue on that
> package's repository instead.
> 
> Thanks for contributing to the Julia project!
> \--\>
> In brief: Julia println output speed seems oddly slow, or costly, in an interactive terminal compare to several other languages. The slow behavior is only occurring in an interactive terminal (tried several such as gnome-terminal, xterm, qterminal, sakura, emacs-vterm). No slowness are visible when the standard output is redirected.
> 
> 1) In details (Linux Debian sid, julia 1.5.3, similar behavior on several x86\_64 (Intel, AMD))
> I wrote recursive Fibonacci computation with printf inside (Julia code below), in several languages for, e.g., demonstrating the synchronization in a terminal for my OS lecture. Julia computation performance is on par with C, C++, Rust, Fortran, Go, Crystal, without the println, but, with the println, Julia is much much slower (2.5 - 6.5 times slower) than even python3, perl5, ruby or node-js. Only Raku is slower but because the Raku 2021.09 computation are still very slow.
> 
> If the output is redirected to /dev/null, Julia is again on par with the fastest languages.
> The most comparable language I tried, "crystal" (ruby compilation with LLVM), does not have the same behavior.
> 
> 2) Remarks:
> According to /usr/bin/time ('time" package in Debian) Julia seems to spend much more time in the kernel: twice the time compare to perl or python.
> 
> perf trace julia... records roughly 4M syscalls for fibo(30) compare to roughly 1M in C, perl or python, and 2M for crystal
> 
> perf record/report indicates VDSO gettimeofday at the top (3%)
> 
> 3) My Fibonacci code:
> \`\`\`julia
> import Printf: @printf
> 
> function fibo\_println(n)
> if n \< 2
> return n
> end
> val = fibo\_println(n-1) + fibo\_println(n-2)
> println(val)
> return val
> end
> 
> n = 20
> if length(ARGS) \> 0
> n = parse(Int64, ARGS\[1\])
> end
> 
> v, t = @timed fibo\_println(n)
> @printf(stderr, "julia fibo(%d)= %lld en %lld s\\n", n, v, t)
> \`\`\`

> <https://github.com/JuliaLang/julia/issues/36639>
>
> https://discourse.julialang.org/t/why-is-printing-to-a-terminal-slow/42987
> 
> Re…quires a terminal that can render output fast (seems like iTerm2 doesn't) to demonstrate.

from

> [@Why is printing to a terminal slow?](https://discourse.julialang.org/t/why-is-printing-to-a-terminal-slow/42987/22):
>
> A different use of printing to stdout/stderr is to pipe output through less (or similar pager) to be able to inspect the output interactively without having to do a full (long) run. E.g. grep for certain strings in the output to check a condition, then letting the program continue until the next matching line, etc. I find this very useful during development. In this case you will also hit upon the slower output of Julia compared to Python. A simple (rough, due to the user keyboard interaction)…

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 13, 2023, 11:57pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/10 "2023-04-13T23:57:21Z")

</div>

This is why mixing up multiple things together isn’t helpful: the fact that printing might be slow isn’t surpring at all, and trying to optimise multiple things together when there’s a single significant bottleneck is a waste of time.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [April 13, 2023, 11:59pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/11 "2023-04-13T23:59:40Z")

</div>

We can start with a program with a problem and then reduce from there.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [April 14, 2023, 12:14am UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/12 "2023-04-14T00:14:22Z")

</div>

With buffering it’s faster:

```julia
import Base: parse

parse(x) = y -> parse(x,y)
@time begin
    io = IOBuffer()
    const lines = readlines("random_numbers.txt")
    rows = [parse(Int, l) for l in lines]
    sort!(rows)
    reverse!(rows)
    println.(io, rows)
    write(stdout, take!(io))
end;

  1.774918 seconds (5.14 M allocations: 188.944 MiB, 9.57% gc time, 6.51% compilation time)

```

compared to 5.5 s in Python.

---

<div class="post-metadata">

**Author:** ![lucasmsoares96](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lucasmsoares96/32/38743_2.png) [@lucasmsoares96](https://discourse.julialang.org/u/lucasmsoares96)\
**Post date:** [April 14, 2023, 12:22am UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/13 "2023-04-14T00:22:12Z")

</div>

Amazing!! Thank you very much!

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [April 14, 2023, 8:45am UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/14 "2023-04-14T08:45:12Z")

</div>

> [@jar1](#):
>
> ```julia
> sort!(rows)
> reverse!(rows)
> 
> ```

It is more idiomatic to simply sort in reverse directly:

```julia
sort!(rows; rev=true)

```

---

<div class="post-metadata">

**Author:** ![Mateusz\_K](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateusz_k/32/31832_2.png) [@Mateusz\_K](https://discourse.julialang.org/u/Mateusz_K)\
**Post date:** [April 18, 2023, 12:18pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/15 "2023-04-18T12:18:12Z")

</div>

Keep in mind that you are comparing Python’s TimSort implemented in C, against Julia’s default QuickSort. Which are not only different algorithms but also C+Python’s overhead is compared against pure Julia solution. Fair comparison would be implementing this algorithm in Python and than comparing. It’s just silly otherwise, because you basically start another program from Python to make a claim about python. Julia can also call C routines.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [April 18, 2023, 1:03pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/16 "2023-04-18T13:03:14Z")

</div>

I don’t think it is silly because these are the default sorting routines, which is what the vast majority of people will use.

---

<div class="post-metadata">

**Author:** ![Mateusz\_K](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateusz_k/32/31832_2.png) [@Mateusz\_K](https://discourse.julialang.org/u/Mateusz_K)\
**Post date:** [April 18, 2023, 1:46pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/17 "2023-04-18T13:46:01Z")

</div>

What i am saying is that conclusion is false, regardless of what defaults people would use. It’s the same as calling C library form Julia in an attempt to benchmark Julia’s speed. That’s just dishonest benchmark regardless of what defaults are. Julia is good at certain things, so is Python but calling another software, leave alone another algorithm to say something about language is wrong. He could compare algorithms by C call from one of languages, if he has wanted to compare algorithms. He could compare implementation in these two languages if he wanted to compare languages. Julia has all sorts of sorting algorithms, so does Python, but timing how things are dispatched carries almost no information about how fast Python is. It’s missleading information to someone who is trying to learn new language for example.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 18, 2023, 1:57pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/18 "2023-04-18T13:57:11Z")

</div>

I disagree with this. It’s not unreasonable to expect Julia to be faster than the C code python calls, and when bench-marking sorting vs python, the relevant time is the timsort vs the default Julia sort. This isn’t a great sorting benchmark for other reasons (i.e. most of the time is IO), but it is a decent benchmark of doing basic data science in Julia vs python.

---

<div class="post-metadata">

**Author:** ![Mateusz\_K](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateusz_k/32/31832_2.png) [@Mateusz\_K](https://discourse.julialang.org/u/Mateusz_K)\
**Post date:** [April 18, 2023, 3:10pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/19 "2023-04-18T15:10:23Z")

</div>

To me Julia’s website has already benchmarks done properly, comparing what it claims to be comparing. There C seems to be baseline for most of tests. Why would it be slower ? Just have a look. You typically don’t benchmark numpy calls to tell that python is fast, because the very reason of having numpy in the first place is that Python is absolutely slow. But if you do make such a claim, be honest and say it’s numpy’s speed. Regarding data science, lots of people mean different thing by that, but for applications where sort() call speed matters, is probably not the application you benefit from Python. I use Python a lot but it’s absolutely a terrible tool for applications where speed matters, such as algorithms development. As soon as you want something that is not in toolbox you are screwed. Most of stuff your run in Python is not even Python because authors that prise it so much shy from implementing it in their very own favourite language.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [April 18, 2023, 3:12pm UTC](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453/20 "2023-04-18T15:12:58Z")

</div>

In the end, everything just calls machine instructions. I think it’s very reasonable to measure the “speed” of a language based on how easy it is to write performant code. For many use cases, Python is fast because numpy is fast. I don’t think that’s some kind of “gotcha,” it’s just true.

> it’s absolutely a terrible tool for applications where speed matters

well, except for nearly 100% of mainstream deep learning

[Next page](https://discourse.julialang.org/t/julia-slower-than-python-to-sort-and-reverse-a-list-of-integers/97453.md?page=2)
