Skip to content

Use direct pointers as Type IDs #2745

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 4 commits into from
Apr 13, 2020
Merged

Conversation

tlively
Copy link
Member

@tlively tlively commented Apr 10, 2020

Instead of using indices into the global interned type table. This
means that a lock is never needed to access an expanded Type. The
Type lock is now only acquired when a complex Type is created. On a
real-world wasm2js workload this improves wall clock time by 23% on my
machine with 72 cores and makes traffic on the Type lock entirely
insignificant.

Before

72 cores
real 6.914s
user 184.014s
sys 3.995s

1 core
real 25.903s
user 25.658s
sys 0.253s

After

72 cores
real 5.349s
user 70.309s
sys 9.691s

1 core
real 25.859s
user 25.615s
sys 0.253s

@tlively tlively requested a review from kripken April 10, 2020 04:34
Instead of using indices into the global interned type table. This
means that a lock is *never* needed to access an expanded Type. The
Type lock is now only acquired when a complex Type is created. On a
real-world wasm2js workload this improves wall clock time by 23% on my
machine with 72 cores and makes traffic on the Type lock entirely
insignificant.

**Before**

72 cores
real    0m6.914s
user    184.014s
sys     0m3.995s

1 core
real    0m25.903s
user    0m25.658s
sys     0m0.253s

**After**

72 cores
real    5.349s
user    70.309s
sys     9.691s

1 core
real    25.859s
user    25.615s
sys     0.253s
@tlively
Copy link
Member Author

tlively commented Apr 10, 2020

Ah, the tracing in the C API needs to be redone because tuple Type IDs (aka the locations in memory of their canonical Type vectors) are not stable between the traced program and the program emitted as the trace.

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

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

Interesting idea!

}
id = typeLists.size();
typeLists.push_back(std::make_unique<std::vector<Type>>(types));
auto* vec = new std::vector<Type>(types);
Copy link
Member

Choose a reason for hiding this comment

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

where is this deleted?

Copy link
Member Author

Choose a reason for hiding this comment

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

NEVER! The canonical type vectors live for the length of the process, just like they did before.

Copy link
Member

Choose a reason for hiding this comment

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

That sounds ok, but before it was making a unique ptr, so it was cleaned up, wasn't it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, the unique_ptr was cleaned up, but only when global destructors run at the end of the program. I could make this a unique_ptr again but I'm not sure whether that has any value.

Copy link
Member

Choose a reason for hiding this comment

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

It would avoid false positives with leak detection tools. I'm unsure myself if that is worth the cost.

@tlively
Copy link
Member Author

tlively commented Apr 13, 2020

@kripken The latest commit adds unique_ptrs to avoid false leaks and switches to using a normal mutex for simplicity. I think this should be good to go now.

// Track unique_ptrs for constructed types to avoid leaks
std::vector<std::unique_ptr<std::vector<Type>>> constructedTypes;

// Maps from type vectors to the canonical Type IS
Copy link
Member

Choose a reason for hiding this comment

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

what is IS here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, should be ID.

}
if (types.size() == 1) {
*this = types[0];
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

I think I don't understand how this all works yet (maybe some overview in types.h?). Here in init we take a lock on anything that doesn't have 0 or 1 elements. Are we somehow not calling init as much? If so I missed that part (or something else).

Copy link
Member Author

Choose a reason for hiding this comment

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

The problem was never that we called init a lot, it was that we called expand a lot and it acquired the lock. Now expand never acquires the lock. I'll add documentation about how the IDs work in the header.

Copy link
Member

Choose a reason for hiding this comment

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

Right, thanks. Now I get it!

@tlively tlively merged commit c16bfee into WebAssembly:master Apr 13, 2020
@kripken
Copy link
Member

kripken commented Apr 13, 2020

This seems to have hit an error on the mac CI after landing: https://travis-ci.org/github/WebAssembly/binaryen/jobs/674594365

@tlively tlively deleted the type-pointers branch April 24, 2020 23:26
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