The point of PNaCl was to overcome or remove some of the constraints that come with the JavaScript language, like the lack of a concurrency model. This necessitates a new runtime. Since a new runtime was required anyways, Google decided to expend the engineering effort to make it as similar to native code as possible in terms of capabilities and performance, while also maintaining security.
The point of asm.js was to not include another runtime in the browser, but still meet the needs of the programs that PNaCl was trying to serve. Because it plays within the bounds of JavaScript it doesn't meet all the needs that PNaCl does (again, like concurrency), but it still allows native-like programming.
Also, Native Client, but apparently not PNaCl, supports SIMD, while asm.js does not.
Of course, both PNaCl and asm.js are evolving, so asm.js may be able to eventually support those features somehow, and PNaCl may get additional features.
Some information about features PNaCl supports are here: https://developers.google.com/native-client/dev/faq
Both are basically intended as a target for LLVM-compiled code, so lots of similarities, but the main difference is that asm.js is a subset of JS so it runs in any JS engine, while PNaCl is different. Aside from that, there are lots of technical differences, but it's hard to say which actually matter in the long run. To quickly summarize, right now asm.js tends to run a little more slowly than PNaCl but start up a little more quickly. But engineers on PNaCL and on JS engines intend to shrink those differences over time, and there is no reason in principle why they won't succeed.
To judge for yourself, you can see some comparisons between PNaCl and asm.js in these two sites:
http://www.flohofwoe.net/demos.html
http://trypepperjs.appspot.com/
My impression is that the perf differences are not that noticeable already. For example, the bullet demo in the second one seems to run slightly faster in PNaCl than asm.js. However, profiling shows that 65% of time is spent in three.js rendering code, not in asm.js, so perhaps rendering differences account for most of the disparity, and it mostly isn't comparing asm.js to PNaCl.
Take this naive fibonacci function: function fib(n) return n<2 and n or fib(n-1)+fib(n-2) end print(fib(30))
On my machine, it completes in less than a second on PNaCl, but takes nearly 10 seconds to complete in emscripten.
http://kripken.github.io/lua.vm.js/repl.html
But even that is already out of date ;) just this week I found that I was building Lua with a bad choice of optimization flags. We include Lua VM benchmarks in the emscripten test suite, so for the latest numbers (with the proper optimization flags), see
https://docs.google.com/spreadsheet/ccc?key=0AkuGewEm05tZdFd...
It's possible to run the Lua VM in JS at only about 50% slower than a native build.
edit: fix link
Regarding lua, I updated the lua vm project, and tried your fibonacci function from before in the repl
http://kripken.github.io/lua.vm.js/repl.html
Looks like in both firefox and chrome it runs in about a second in JS, which feels about the same as the time it takes in PNaCl in chrome on
EDIT: And pepper.js is essentially a response back to asm.js and its "run, albeit with less performance optimization, on any modern JS engine".
I'd like to see the benchmarks before assuming that, but if this leads to letting me use Haskell in the browser, I'll be all over it.