Closed Bug 470779 Opened 12 years ago Closed 9 years ago

TM: 6X slower with trace-abort before short inner loop, due to oscillating between interpreter and JIT

Categories

(Core :: JavaScript Engine, defect, P2)

x86
macOS
defect

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: jruderman, Unassigned)

References

Details

(Keywords: perf, testcase)

for (var i = 0; i < 500000; ++i) {
  ~{};
  for (var j = 0; j < 4; ++j) {
  }
}

3X slower with JIT enabled

for (var i = 0; i < 500000; ++i) {
  true % 3;
  for (var j = 0; j < 4; ++j) {
  }
}

6X slower with JIT enabled

The weird thing is that if I remove the inner loop, I get an abort during recording, so it's only 10-30% slower.  But with the inner loop present, it traces and then keeps hitting a side exit(?), making it several times slower.  Aborting is probably reasonable for these testcases; why does the inner loop prevent it from aborting?
The side exit is expected, because it doesn't take long for j to hit 4.  I suspect the overhead of entering and exiting the trace for the inner loop every time is the problem here, but I have not tested this theory.

Do we have any heuristics to blacklist and trash trace trees that consistently execute for only a short time before side exiting?
Oh, I get it.  It *does* abort recording of the outer loop, but still records the inner loop, forcing repeated jumps between the interpreter and the JIT.  Nasty.
Summary: TM: 6X slower with unhappy operator before inner loop (fails to abort recording?) → TM: 6X slower with trace-abort before short inner loop, due to oscillating between interpreter and JIT
The problem here is that we create an inner loop, but we don't capture the outer loop around it due to the ~{}; and true % 3 (which makes us abort). The inner loop is a net perf loss because it doesn't do anything except unpack/repack its stack. The outer loop could embed the inner loop if we trace that path. I think the goal is here to not abort for any sensible cose. How sensible is ~{} though?
Duplicate of this bug: 470738
> I think the goal is here to not abort for any sensible code. 
> How sensible is ~{} though?

Not very.  But I believe DOM calls aren't going to be traced for Firefox 3.1, so I worry that this issue will slow down scripts whose only "mistake" is to mix DOM manipulation with light computation.
Flags: blocking1.9.1?
not blocking on ~{}
Flags: wanted1.9.1+
Flags: blocking1.9.1?
Flags: blocking1.9.1-
If the thing causing the abort were a DOM call, this would be nothing too serious, since "~{}" is going to be real fast in comparison.

Of course, if you can make this a real case in a web page, let's reconsider.
Priority: -- → P2
Bug 535925 has a type-unstable outer loop (which is blacklisted) and a short, traced inner loop. Performance is 15.3s with JIT, 8.7s without. It's reduced from a real-world example.
Blocks: 535925
For me the second example from comment 1 seems to trace now. The first example doesn't (500,000 exits) and using an optimised build on windows is about 50% slower with JIT.
Still a problem in the JM+TI world?
Run the tests and see?
With a current shell:
Testcase 1
js -b 470779-1.js
runtime = 775.066 ms
js -b -m -n 470779-1.js
runtime = 381.890 ms

Testcase 2
js -b 470779-2.js
runtime = 324.557 ms
js -b -m -n 470779-2.js
runtime = 11.616 ms

Looks better to me!
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.