Skip to content

Importlib #1018

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 31 commits into from
Jun 12, 2019
Merged

Importlib #1018

merged 31 commits into from
Jun 12, 2019

Conversation

palaviv
Copy link
Contributor

@palaviv palaviv commented Jun 5, 2019

This is a work in progress on the imprtlib module. I would love to get input as early as possible so please fill free to comment. There is still work to do to make everything works but the steps are:

  1. Make importlib._install work.
  2. Support bootstrap_external.
  3. Change __import__ to use the Importers in sys.meta_path

A big question I am not sure about is where to initialize the importlib? In Cpython it is done as part of the lifecycle. Where do you think we should do it?

@palaviv palaviv mentioned this pull request Jun 5, 2019
11 tasks
@palaviv
Copy link
Contributor Author

palaviv commented Jun 8, 2019

Should we put a FIXME or XXX here so that we can easily find it later?

Maybe XXX as I do not think we would like to fix this. I do not thin we should split _os into posix and nt as rust give us an abstraction over the OS on most methods.

@windelbouwman
Copy link
Contributor

This importlib stuff is pretty complex, thank you for having a look at this. The change looks pretty okay to me. It looks like pretty entangled code of frozen, import and the vm. Does the concat! macro work like os.path.join?

@windelbouwman
Copy link
Contributor

A big question I am not sure about is where to initialize the importlib? In Cpython it is done as part of the lifecycle. Where do you think we should do it?

I would be my preference to initialize this optionally, seperate from the vm, so that we could re-use the vm without importlib if this is required. So in this case, I would suggest to initialize importlib in src/main.rs. In any case it is good to have a seperate importlib.rs file which contains the logic, but it does not have to be used always.

@palaviv
Copy link
Contributor Author

palaviv commented Jun 9, 2019

Why would you like to make this optional? For the WASM we can just replace the PathFinder for sys.meta_path with something specific for WASM.

@windelbouwman
Copy link
Contributor

I would like to make this optional for cases where you do not want to to use importlib. Or do you always use importlib? What is the fallback scenario? I'm not familiar with importlib, if it is the only option for importing stuff, it should not be optional, but baked in.

@palaviv
Copy link
Contributor Author

palaviv commented Jun 9, 2019

In Cpython you always use the frozen importlib _bootstrap.__import__ function. I think that we should always use it as well instead of having a fallback to the current code.

let name_obj = vm.new_str(self.name.clone());
if let Some(ref dict) = &self.into_object().dict {
let mod_dict = dict.clone();
mod_dict.set_item("__name__", name_obj, vm)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

This set_item will happen each time the dict is retrieved. Is there a way to create the dict when the module is constructed? So in init or new?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@palaviv palaviv marked this pull request as ready for review June 10, 2019 19:09
@palaviv
Copy link
Contributor Author

palaviv commented Jun 10, 2019

This actually pass the tests now 🎉 🎉 🎉

A few comments:

  1. The imports are slower then before.
  2. We should change the import parsing to pass the from_list as one list.
  3. I need to fix the change with name I did in objmodule (Waiting for response on gitter).
  4. Why are we using import on vm.class and vm.try_class?

@coolreader18
Copy link
Member

Why are we using import on vm.class and vm.try_class?

What's the alternative? We need to know what class a pyclass is associated with, and the best way we have so far is to store it in a module and import it in class. I did a little work in storing a HashMap<TypeId, PyClassRef> on VirtualMachine a while back, but I was busy then and nothing really came of it.

@palaviv
Copy link
Contributor Author

palaviv commented Jun 11, 2019

Thanks @coolreader18 I just had some infinite loop problems and wanted to understand more the logic.

About the import being slow. When running the following script:

import time

start = time.time()
import os
print(time.time() - start)

When I run this without the --release flag I get ~13 [sec] while with the flag I get ~0.5 [sec].

@palaviv palaviv changed the title [WIP] importlib Importlib Jun 11, 2019
@codecov-io
Copy link

codecov-io commented Jun 11, 2019

Codecov Report

Merging #1018 into master will increase coverage by 0.22%.
The diff coverage is 67.21%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1018      +/-   ##
==========================================
+ Coverage   64.74%   64.96%   +0.22%     
==========================================
  Files          97       97              
  Lines       17093    17155      +62     
  Branches     3811     3832      +21     
==========================================
+ Hits        11067    11145      +78     
+ Misses       3443     3398      -45     
- Partials     2583     2612      +29
Impacted Files Coverage Δ
vm/src/stdlib/io.rs 63.49% <100%> (ø) ⬆️
vm/src/stdlib/os.rs 71.04% <100%> (+1.07%) ⬆️
vm/src/sysmodule.rs 61.2% <100%> (+2.11%) ⬆️
vm/src/frozen.rs 100% <100%> (ø) ⬆️
vm/src/stdlib/mod.rs 100% <100%> (ø) ⬆️
vm/src/frame.rs 69.72% <40%> (+0.71%) ⬆️
vm/src/import.rs 62.19% <45.71%> (-12.36%) ⬇️
vm/src/stdlib/thread.rs 60% <61.9%> (+60%) ⬆️
vm/src/vm.rs 74.8% <75%> (+0.36%) ⬆️
vm/src/obj/objmodule.rs 76.92% <75%> (+3.58%) ⬆️
... and 13 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 740e838...1de9f73. Read the comment docs.

@palaviv
Copy link
Contributor Author

palaviv commented Jun 11, 2019

After looking more into the slowness of the import I saw most of the time we lost is by calling the python function __import__ on already loaded modules. I optimized the call for import to first check from rust for loaded module before calling the python __import__. This change the none --release time to ~5[sec] compared to the ~3[sec] of the current master. The --release version is 0.17[sec] while in the master it is 0.1 [sec].

I know this is about 1.5-2 times slower then the current import system but I believe we can optimize this at later stage. Do you guys think this is ready to be merged?

@coolreader18
Copy link
Member

This looks good to me at this point, @windelbouwman is this good to merge?

@coolreader18
Copy link
Member

Also, I'm sure that imports will speed up even more once we have pyc serialization and use __pycache__.

self.ctx.exceptions.import_error.clone(),
"__import__ not found".to_string(),
)),
pub fn import(&self, module: &str, from_list: &PyObjectRef) -> PyResult {
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be good to move this whole function to the import.rs file. But that is something we can do later on.

}
}

pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult {
Copy link
Contributor

Choose a reason for hiding this comment

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

This function name is slightly confusing with the existing function builtin_import in the file builtins.rs. We should come up with some better name, preferably not having the the word builtin in it. Maybe something like internal, or baked in, or rust lib.

@windelbouwman
Copy link
Contributor

Looks good to me!

@windelbouwman windelbouwman merged commit 3f343af into RustPython:master Jun 12, 2019
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.

4 participants