-
Notifications
You must be signed in to change notification settings - Fork 28.1k
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
[SPARK-13640][SQL] Synchronize ScalaReflection.mirror method. #11487
Conversation
Test build #52375 has finished for PR 11487 at commit
|
I assume it still works in 2.11, and is at worst redundant but doesn't hurt much. This is definitely the right lock? Maybe a comment pointing to why that is correct would help since it isn't obvious |
This PR can solve the issue mentioned in SPARK-10719 right? |
@zsxwing who reported SPARK-10719. |
Test build #52397 has finished for PR 11487 at commit
|
SPARK-10719 is different. I don't think this one will resolve SPARK-10719 since the issue is in the compiler generated codes which never call |
Jenkins, retest this please |
Test build #52412 has finished for PR 11487 at commit
|
Jenkins, retest this please |
Test build #52441 has finished for PR 11487 at commit
|
|
||
private def testThreadSafetyFor(name: String)(exec: () => Any) = { | ||
test(s"thread safety of ${name}") { | ||
for (_ <- 0 until 100) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(0 until 100).foreach
? probably just a matter of taste but it's symmetrical with your inner loop then.
You can import java.net.URLClassLoader
.
It doesn't really seem like you need a method here; it took a moment to see there was a test in here.
Maybe it's obvious to you but why do all these classes/methods need to be tested separately?
And is this locking still safe in 2.11?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srowen Thank you for your comment.
(0 until 100).foreach
?
I repeated the test 100 times here because it is for thread-safety. Thread safety problem sometimes happens but sometimes doesn't.
You can import
java.net.URLClassLoader
.
I'll modify to use import.
It doesn't really seem like you need a method here; it took a moment to see there was a test in here.
I'll modify to move out of the method.
Maybe it's obvious to you but why do all these classes/methods need to be tested separately?
The methods are public, i.e. can be called by multi-thread, so I thought these also need to be tested.
But I'm wondering some of them could be removed?
And is this locking still safe in 2.11?
Yes, reflection in Scala 2.11 is thread-safe.
If we don't support Scala 2.10, these lockings in ScalaReflection
would not be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I understand repeating it 100 times, but your idiom for iterating n times is different on two nearby lines.
I actually meant the opposite -- remove the helper method but run test
s in a loop still -- but leave it.
My question was more like, does the extra locking cause trouble in 2.11? I know you said 2.11 doesn't need this change per se.
Test build #52542 has finished for PR 11487 at commit
|
Test build #52541 has finished for PR 11487 at commit
|
I think the extra locking cause a little performance penalty while building logical plan in a driver process but it is much smaller than execution time. |
Test build #52562 has finished for PR 11487 at commit
|
OK, that seems reasonable. I was more wondering if we risk some deadlock in 2.11, but the tests are also potentially testing for that problem as well. |
Merged to master |
@srowen Thank you for merging this and your review. |
Will this fix be applyied to 1.6 version? |
Could be; I had not done so to be conservative, since I wasn't entirely sure of the implication, and sounded like a rare issue. But if you have some reasonable argument it warrants back-porting, I think that's possible. |
@timotta FYI, this one doesn't resolve SPARK-10719. If you want to use DataFrame in multiple threads with Scala 2.10, you may still encounter SPARK-10719. Since the Scala community doesn't want to fix SI-6240 for 2.10, I don't think there is anything to do in Spark. Maybe the best option is using Scala 2.11. |
@zsxwing I could use scala 2.11 but if it's not a spark issue, Spark should distribute as default with scala 2.11 not 2.10, since there is this bug. |
@zsxwing i think the issued im looking to fix is that one: https://issues.apache.org/jira/browse/SPARK-13640 |
Spark 2.0.0 will use 2.11 by default. However, we cannot do it for 1.6 as it's only a maintenance branch.
I meant the fix for SPARK-13640 doesn't fix all race conditions in DataFrame. |
## What changes were proposed in this pull request? `ScalaReflection.mirror` method should be synchronized when scala version is `2.10` because `universe.runtimeMirror` is not thread safe. ## How was this patch tested? I added a test to check thread safety of `ScalaRefection.mirror` method in `ScalaReflectionSuite`, which will throw the following Exception in Scala `2.10` without this patch: ``` [info] - thread safety of mirror *** FAILED *** (49 milliseconds) [info] java.lang.UnsupportedOperationException: tail of empty list [info] at scala.collection.immutable.Nil$.tail(List.scala:339) [info] at scala.collection.immutable.Nil$.tail(List.scala:334) [info] at scala.reflect.internal.SymbolTable.popPhase(SymbolTable.scala:172) [info] at scala.reflect.internal.Symbols$Symbol.unsafeTypeParams(Symbols.scala:1477) [info] at scala.reflect.internal.Symbols$TypeSymbol.tpe(Symbols.scala:2777) [info] at scala.reflect.internal.Mirrors$RootsBase.init(Mirrors.scala:235) [info] at scala.reflect.runtime.JavaMirrors$class.createMirror(JavaMirrors.scala:34) [info] at scala.reflect.runtime.JavaMirrors$class.runtimeMirror(JavaMirrors.scala:61) [info] at scala.reflect.runtime.JavaUniverse.runtimeMirror(JavaUniverse.scala:12) [info] at scala.reflect.runtime.JavaUniverse.runtimeMirror(JavaUniverse.scala:12) [info] at org.apache.spark.sql.catalyst.ScalaReflection$.mirror(ScalaReflection.scala:36) [info] at org.apache.spark.sql.catalyst.ScalaReflectionSuite$$anonfun$12$$anonfun$apply$mcV$sp$1$$anonfun$apply$1$$anonfun$apply$2.apply(ScalaReflectionSuite.scala:256) [info] at org.apache.spark.sql.catalyst.ScalaReflectionSuite$$anonfun$12$$anonfun$apply$mcV$sp$1$$anonfun$apply$1$$anonfun$apply$2.apply(ScalaReflectionSuite.scala:252) [info] at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) [info] at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) [info] at scala.concurrent.impl.ExecutionContextImpl$$anon$3.exec(ExecutionContextImpl.scala:107) [info] at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [info] at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [info] at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [info] at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) ``` Notice that the test will pass when Scala version is `2.11`. Author: Takuya UESHIN <ueshin@happy-camper.st> Closes apache#11487 from ueshin/issues/SPARK-13640.
@ueshin Have you found this test to pass consistently on 2.10? It seems we don't actually run these tests on 2.10 at all anymore, but when I run locally, say with
it sometimes works, but sometimes fails with a variety of failures like:
or
It seems like a pretty rare race -- any attempt I make to add any logging, or even a try/catch, makes it seem to disappear (at least, less than 1 in 10 runs after any changes). Maybe this is just the same as SPARK-10719, and there isn't anything better we can do here? |
@squito Thank you for your report. |
What changes were proposed in this pull request?
ScalaReflection.mirror
method should be synchronized when scala version is2.10
becauseuniverse.runtimeMirror
is not thread safe.How was this patch tested?
I added a test to check thread safety of
ScalaRefection.mirror
method inScalaReflectionSuite
, which will throw the following Exception in Scala2.10
without this patch:Notice that the test will pass when Scala version is
2.11
.