Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

O(n^2) scaling in llvm symbol lookup #15619

Closed
yuyichao opened this issue Mar 24, 2016 · 4 comments
Closed

O(n^2) scaling in llvm symbol lookup #15619

yuyichao opened this issue Mar 24, 2016 · 4 comments
Labels
compiler:codegen Generation of LLVM IR and native code performance Must go faster

Comments

@yuyichao
Copy link
Contributor

While fiddling #14846 with gdb folks I noticed that there's a O(n^2) scaling in our own JIT too.

The test is done on patched llvm 3.7.1 with this script which is basically emitting a lot of small functions with different names by,

for i in 1:n
    f = symbol("f$i")
    @eval $f() = $i
    @eval $f()
end

Ploting the time vs n on a log-log scale it's very clear that the O(n^2) scaling takes over for n > 10k.

timing

The profile (done with perf since I was profiling gdb with the same command) with n = 50000 is,

profile

and it seems that most of the time is spent in the symbol lookup (some of the other functions are also quite significant but the symbol lookup seems to be the worst).

@vtjnash and @carnaval suggested that llvm has a O(n) object file look up and we might need to replace it with our own hash table in jitlayer.cpp.

Also c.c. @Keno

@yuyichao yuyichao added the performance Must go faster label Mar 24, 2016
@JeffBezanson JeffBezanson added the compiler:codegen Generation of LLVM IR and native code label Mar 24, 2016
@jrevels jrevels added the potential benchmark Could make a good benchmark in BaseBenchmarks label Mar 24, 2016
@timholy
Copy link
Member

timholy commented Mar 24, 2016

Nice detective work as always, @yuyichao.

@vtjnash
Copy link
Member

vtjnash commented Mar 25, 2016

it's probably worthwhile to memoize the result of findSymbol in a StringMap<orc::JITSymbol> (at https://github.com/JuliaLang/julia/blob/master/src/jitlayers.cpp#L398), since we can end up jitting such an insane number of small object files and this call is linear in the number of object files that have been added

@vtjnash
Copy link
Member

vtjnash commented Mar 26, 2016

i've created a version of yuyichao's script that also emits a plot and shows my fix will be O(1): https://gist.github.com/vtjnash/89cff0605d29fe968e56 (with total compile time const on this benchmark roughly 2x the old jit, but at least with constant scaling now)

vtjnash added a commit that referenced this issue Mar 26, 2016
CompileLayer.findSymbol is O(n) in the number of modules that have been emitted
but we can pre-compute the result of findSymbolIn when notified that an object has been emitted and store it in one hash table for the JIT

fix #15619
vtjnash added a commit that referenced this issue Mar 28, 2016
CompileLayer.findSymbol is O(n) in the number of modules that have been emitted
but we can pre-compute the result of findSymbolIn when notified that an object has been emitted and store it in one hash table for the JIT

fix #15619
@yuyichao
Copy link
Contributor Author

yuyichao commented Apr 2, 2016

Reported upstream https://llvm.org/bugs/show_bug.cgi?id=27188

@KristofferC KristofferC removed the potential benchmark Could make a good benchmark in BaseBenchmarks label Oct 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:codegen Generation of LLVM IR and native code performance Must go faster
Projects
None yet
Development

No branches or pull requests

6 participants