Skip to content

Factor is terribly slow #49

@enedil

Description

@enedil

Hello.
I believe that after finding every consecutive prime factor, performing isprime on resultant is harmful for performance of such function. Consider such snippet:

number = reduce(*, 1, Primes.PRIMES)
tic(); factor(number); toc()
# already running for 15 minutes, still didn't halt

Compare it with equivalent Python:

from operator import mul
from sympy import primerange, factorint
number = reduce(mul, primerange(1, 2**16), 1)
%timeit factorint(number)
# 1 loops, best of 3: 16.8 s per loop

Considering the fact that sympy is written in pure Python, this is pathetic.

Profiling Julia version brings such result (this time taking the product of first 3000 primes):

WARNING: The profile data buffer is full; profiling probably terminated
before your program finished. To profile for longer runs, call Profile.init
with a larger buffer and/or larger delay.
18816 ./event.jl:68; (::Base.REPL.##3#4{Base.REPL.REPLBackend})()
 18816 ./REPL.jl:95; macro expansion
  18816 ./REPL.jl:64; eval_user_input(::Any, ::Base.REPL.REPLBackend)
   18816 ./<missing>:?; anonymous
    18816 ./profile.jl:16; macro expansion;
     18816 /home/enedil/.julia/v0.5/Primes/src/Primes.jl:312; factor(::BigInt)
      1     ./dict.jl:701; factor!(::BigInt, ::Dict{BigInt,Int64})
      11    /home/enedil/.julia/v0.5/Primes/src/Primes.jl:267; factor!(::BigInt, ::Dict{BigInt,Int64})
       11 ./gmp.jl:110; convert
      3     /home/enedil/.julia/v0.5/Primes/src/Primes.jl:268; factor!(::BigInt, ::Dict{BigInt,Int64})
       1 ./gmp.jl:255; rem
       2 ./gmp.jl:256; rem
      2     /home/enedil/.julia/v0.5/Primes/src/Primes.jl:269; factor!(::BigInt, ::Dict{BigInt,Int64})
       1 ./dict.jl:644; setindex!(::Dict{BigInt,Int64}, ::Int64, ::BigInt)
      3     /home/enedil/.julia/v0.5/Primes/src/Primes.jl:270; factor!(::BigInt, ::Dict{BigInt,Int64})
       3 ./gmp.jl:256; div
      6     /home/enedil/.julia/v0.5/Primes/src/Primes.jl:271; factor!(::BigInt, ::Dict{BigInt,Int64})
       6 ./gmp.jl:255; rem
      18789 /home/enedil/.julia/v0.5/Primes/src/Primes.jl:276; factor!(::BigInt, ::Dict{BigInt,Int64})
       18789 /home/enedil/.julia/v0.5/Primes/src/Primes.jl:190; isprime
        18789 /home/enedil/.julia/v0.5/Primes/src/Primes.jl:190; isprime

Ha! I suspected that checking is number is prime after excluding one particular factor is superfluous, and I know it's basically one of the worst cases for such design, but after all, how such difference in time (with sympy) could be explained?

I propose the call to isprime to be supressed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions