Skip to content

avoid duplicate call to dist/bin/common via refactored scalac #12197

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

Merged
merged 10 commits into from
Apr 27, 2021
Merged

avoid duplicate call to dist/bin/common via refactored scalac #12197

merged 10 commits into from
Apr 27, 2021

Conversation

philwalk
Copy link
Contributor

This is an alternate fix for script startup latency caused by redundant sourcing of bin/common within bin/scala when launching a script. See #11698 for the original proposal, based on exporting relevant environment variables and conditionally sourcing bin/common.

This PR instead moves additional common code from bin/scalac to functions in bin/common.
The new functions are used to launch the compiler directly from within bin/scala.

In addition, one test was updated to accommodate the change:

dotty.tools.scripting.ClasspathTests

Another test was updated to remove a timezone dependency:

dotty.tools.repl.ScriptedTests

dist/bin/scala Outdated
eval "\"$PROG_HOME/bin/scalac\" ${cp_arg-} ${java_options[@]} ${residual_args[@]} -script $target_script ${script_args[@]}"
set -- ${cp_arg-} ${java_options[@]} ${residual_args[@]} -script "$target_script" ${script_args[@]}
PROG_MAIN=$ScriptingMain
prepScalacCommandLine "$@"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering what arguments are expected to be parsed here? If it's only 1 or 2, can we do it in bin/scala instead?

Copy link
Contributor Author

@philwalk philwalk Apr 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered trying to do a less extensive change, but ran into problems.

One concern is has to do with alternate ways for launching a script. The following two command lines are currently supported valid ways to launch a script:

scala hello.sc
scalac -script hello.sc

These and other similar issues are tested in project/scripts/winCmdTests, and possibly elsewhere.

My assumption is that we want a functionally neutral refactoring, so scripts should use the same default values, for example default_java_opts="-Xmx768m -Xms768m"

They should leverage a single toolchain classpath, and should have access to and respond the same way to scalac options such as -Oshort, for example. So most of what happens in bin/scalac is needed to produce a functionally equivalent java command line.

Anyway, that's what led me to the current implementation, which can no doubt be improved in various ways.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scalac -script hello.sc

I am not sure if Scala 2 supports the above. If not, I think it does not have to be supported.

My assumption is that we want a functionally neutral refactoring, so scripts should use the same default values, for example default_java_opts="-Xmx768m -Xms768m"

This can be either duplicated or moved to bin/common -- maybe duplicating it is easier for maintenance.

They should leverage a single toolchain classpath, and should have access to and respond the same way to scalac options such as -Oshort, for example. So most of what happens in bin/scalac is needed to produce a functionally equivalent java command line.

Given that bin/scala already parses many options that bin/scalac parses, it does not matter to parse 1-2 more options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that bin/scala already parses many options that bin/scalac parses, it does not matter to parse 1-2 more options.

Okay, I see what you have in mind. I'll will review it again.

I am not sure if Scala 2 supports the above. If not, I think it does not have to be supported.

I don't think it's supported by scala 2, although both ways of launching the script must provide -script <scriptname> on the generated java command line, because compiler/src/dotty/tools/scripting/Main.scala line 12 uses it to distinguish jvm parameters from script filename and args.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liufengyun
Is your idea that we move the command line parsing from bin/common back to bin/scalac and selectively duplicate some of the needed parsing in bin/scala ?

dist/bin/scala Outdated
@@ -165,7 +186,7 @@ elif [ $execute_repl == true ] || [ ${#residual_args[@]} -ne 0 ]; then
cp_arg+="$PSEP$DOTTY_COMP$PSEP$TASTY_CORE$PSEP$DOTTY_INTF$PSEP$SCALA_ASM$PSEP$DOTTY_STAGING$PSEP$DOTTY_TASTY_INSPECTOR"
fi
# exec here would prevent onExit from being called, leaving terminal in unusable state
eval "\"$JAVACMD\"" "$DEBUG" "-classpath \"$cp_arg\"" "${jvm_options[@]}" "${residual_args[@]}"
eval "\"$JAVACMD\"" "$DEBUG" "-classpath \"$cp_arg\"" "${java_args[@]}" "${residual_args[@]}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the refactoring 👍

@philwalk
Copy link
Contributor Author

FYI, this PR resolves a problem in bin/scalac in the way it handles jvm_cp_args, shown here:

# line 79:
  jvm_cp_args="-classpath \"$toolchain\""
# line 101:
  -with-compiler) jvm_cp_args="$PSEP$DOTTY_COMP$PSEP$TASTY_CORE" && shift ;;

In one case, it carries the -classpath prefix, in the other it doesn't. Where it's passed to the jvm on line 129: it was expected to have the prefix. This PR removes the prefix and handles it separately on the jvm command line.

@philwalk
Copy link
Contributor Author

@liufengyun
I have a version that follows your suggestions, and it's now passing tests.
I suspect I should wait to push it until this weekend, to avoid loading the build servers.

@liufengyun
Copy link
Contributor

@liufengyun
I have a version that follows your suggestions, and it's now passing tests.
I suspect I should wait to push it until this weekend, to avoid loading the build servers.

Thanks a lot 👍 You are welcome to push whenever it's ready.

@philwalk
Copy link
Contributor Author

I need to manually test all the various existing command line args in bin/scala, such as -repl etc., which will take awhile.
It's passing tests, but I'm not sure how exhaustive the automated testing is.

@philwalk
Copy link
Contributor Author

philwalk commented Apr 23, 2021

The CLI parsing for bin/scalac and bin/scala are now separated again.
This commit also includes a fair amount of refactoring and cleanup, removing unused variables (.e.g, -quiet).

The operating modes for bin/scala were managed by 3 separate mutually exclusive booleans. It now has a single execution_mode string that unambiguously controls which of the 3 modes are selected.

Comments are added to document the purpose of variables, the required order of arguments, and so forth.

Feedback and suggestions are welcome!

Copy link
Contributor

@liufengyun liufengyun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @philwalk 🎉

Minor: we can replace the two remaining bin/scalac with direct calls, but that can be done in a different PR.

# hashbang can combine args, e.g. "-classpath 'lib/*'"
CLASS_PATH="${1#* *}${PSEP}"
class_path_count+=1
let class_path_count+=1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation above, @philwalk . I'm wondering do we need a || true here and line 74?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 74 is okay because class_path_count is only zero on line 50, and always > 0 on line 74.
I did discover some other places that did need to be changed:

reference to residual_args in line 160:

  if [[ $options_indicator -eq 0 && "${residual_args[@]-}" == "" ]]; then

change "$DEBUG" to ${DEBUG-}" in line 227:

  eval "\"$JAVACMD\"" "${DEBUG-}"  "-classpath \"$repl_cparg\"" "${java_args[@]}" "${residual_args[@]}"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation, @philwalk. Once the two issues you mentioned are addressed, I think we can merge the PR.

@philwalk
Copy link
Contributor Author

Doing manual tests in various shell environments, and if no problems are encountered, I'll push the update.


# debug

DEBUG_STR=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

classpathArgs () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename it to reflect that it's used for the compiler JVM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liufengyun - good idea. I didn't see this until after I pushed changes, so we'll have to do that when we update the two other calls to bin/scalac.

@liufengyun liufengyun merged commit 01eb5a2 into scala:master Apr 27, 2021
@philwalk philwalk deleted the refactored-scalac-startup-latency branch April 27, 2021 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants