Skip to content
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

Add StringMap, NumberMap, and StringSet data structures #10230

Closed
wants to merge 6 commits into from
Closed

Conversation

ghost
Copy link

@ghost ghost commented Aug 9, 2016

This switches us to using native Maps and Sets where possible.
Since we can't guarantee that the native Map will exist, we instead have StringMap and NumberMap for string-keyed and number-keyed maps, with shims using objects and arrays.
Many remaining uses of the old Map may be better off as StringMap, but I've left alone anything that looks public-facing.
I've also mostly left declarationEmitter and emitter alone. When we merge the transforms branch in we should use the new maps there.

I'd like to assign @rakatyal to this but it looks like he's not yet on the available assignees list.

…e available, to replace the old Map, which is now ObjMap.
}

/** String-keyed Map. */
export interface SMap<V> extends MapCommon<string, V> {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think it will be easier to read if you just use StringMap instead of SMap and same as NumberMap for NMap

Copy link
Author

Choose a reason for hiding this comment

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

On that topic, what should we name ObjMap? (The keys aren't objects. The map itself is an object, which is used like a StringMap.)

Copy link
Member

Choose a reason for hiding this comment

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

NumberKeyedMap, StringKeyedMap, ObjectBackedMap. With good autcomplete, there's no real reason for confusing or ambiguous hungarianesque notation.

@@ -1399,7 +1397,7 @@ namespace ts {

const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
typeLiteralSymbol.members = { [symbol.name]: symbol };
typeLiteralSymbol.members = singletonMap(symbol.name, symbol);
Copy link

Choose a reason for hiding this comment

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

What's the purpose of singletonMap?

Copy link
Author

Choose a reason for hiding this comment

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

Thought it was neater than new SMap([[symbol.name, symbol]]).

Copy link
Member

@weswigham weswigham Aug 9, 2016

Choose a reason for hiding this comment

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

Nothing about this is like a singleton in the design pattern sense (it's a loaded term), so the name is a bit confusing. createStringKeyedMap would be more straightforward, if you must wrap the constructor.

@weswigham
Copy link
Member

This appears to sort object type keys (which is causing what should be a transparent change to manifest in our baselines). With this change sort order is now insertion order (which arguably is nice), however this is likely a problem because the polyfills right now don't do the same sorting. (This may surface as node 0.10 failing CI with mismatching baselines once the other bugs are fixed)

export const SSet: SSetConstructor = Set ? Set : ShimSSet;

/** False iff there are any values in the set. */
export function setIsEmpty(set: SSet): boolean {
Copy link

Choose a reason for hiding this comment

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

Should this be isSetEmpty?

@rakatyal
Copy link

rakatyal commented Aug 9, 2016

Could you also please share some numbers on how this effect both memory and performance in the typescript repo and other use cases?

@ghost
Copy link
Author

ghost commented Aug 10, 2016

Overall, we get about a 10% reduction of both memory and total time. (We could get even more by changing the emitter to use StringMaps.)

(Note: since file system accesses are cached, I throw away the first run, which has a large I/O read time.)

VSCode

Testing on the latest checkout of Microsoft/vscode:

Constant:

Files:            1120
Lines:          312630
Nodes:         1591307
Identifiers:    496012
Symbols:        417268
Types:          114545
I/O write:       0.00s (--noEmit)
Emit time:       0.00s (--noEmit)

tsc -p src --noEmit --diagnostics:

Memory used:   704300K 679391K 679408K
I/O read:        0.18s 0.22s 0.19s
Parse time:      5.36s 5.58s 5.60s
Bind time:       1.51s 1.70s 1.64s
Check time:     10.44s 10.24s 9.79s
Total time:     17.30s 17.52s 17.02s

node ../TypeScript/built/local/tsc --noEmit --diagnostics -p src:

Memory used:   593708K 589821K 595477K
I/O read:        0.24s 0.19s 0.17s
Parse time:      5.43s 5.21s 5.01s
Bind time:       1.16s 1.25s 1.43s
Check time:      8.46s 8.97s 9.13s
Total time:     15.05s 15.43s 15.57s

Typescript services

Testing on the src/services directory (in this branch):

Files:              43
Lines:           91284
Nodes:          456582
Identifiers:    168783
Symbols:        156627
Types:           31431
I/O read:        0.04s 0.02s 0.03s 0.02s 0.01s 0.02s

tsc -p src/services --noEmit --diagnostics:

Memory used:   243354K 243332K 235689K
Parse time:      0.75s 0.78s 0.77s
Bind time:       0.46s 0.47s 0.46s
Check time:      3.28s 3.19s 3.24s
Total time:      4.49s 4.43s 4.47s

node ./built/local/tsc.js -p src/services --noEmit --diagnostics

Memory used:   216397K 216644K 217180K
Parse time:      0.79s 0.77s 0.84s
Bind time:       0.39s 0.36s 0.39s
Check time:      2.77s 2.73s 2.84s
Total time:      3.95s 3.87s 4.08s

Single file

Just a file with console.log("Hello world!")

Files:               2
Lines:           19010
Nodes:           98062
Identifiers:     35497
Symbols:         94435
Types:           11926

tsc --diagnostics --noEmit a.ts:

Memory used:    89009K 89023K 89243K
I/O read:        0.00s 0.00s 0.00s
Parse time:      0.25s 0.21s 0.21s
Bind time:       0.10s 0.10s 0.08s
Check time:      0.91s 0.99s 0.91s
Total time:      1.26s 1.30s 1.20s

node ../../../TypeScript/built/local/tsc.js --diagnostics --noEmit a.ts:

Memory used:    82048K 81071K 81771K
I/O read:        0.00s 0.00s 0.00s
Parse time:      0.21s 0.20s 0.20s
Bind time:       0.12s 0.09s 0.09s
Check time:      0.76s 0.64s 0.74s
Total time:      1.09s 0.93s 1.02s

Interactive test

What I did:

Go to vscode repo
`code src`
Use file navigator to go to vs/base/browser/ui/actionbar/actionbar.ts
Then type ctrl-t, "getZoomLevel"
View memory in task manager

Then go to settings and change "typescript.tsdk" to point to my local version, close all tabs, and start over.

"C:\\Program Files\\nodejs\\node_modules\\typescript\\lib": 272.2MB

"C:\\Users\\anhans\\work\\TypeScript\\built\\local": 265.7MB

@ghost ghost changed the title Add SMap and NMap data structures Add StringMap, NumberMap, and StringSet data structures Aug 10, 2016
@mhegazy
Copy link
Contributor

mhegazy commented Sep 13, 2016

@andy-ms what were the numbers if we are using the shims and not the native implementation?

@ghost
Copy link
Author

ghost commented Sep 28, 2016

The shims caused an increase in memory due to indirection: the shim was an object pointing to another object in dictionary mode.

With native maps:

Memory used:   611586K
Parse time:      4.88s
Bind time:       1.26s
Check time:      8.22s
Total time:     14.36s

Memory used:   613703K
Parse time:      5.01s
Bind time:       1.26s
Check time:      8.45s
Total time:     14.72s

Memory used:   613734K
Parse time:      4.99s
Bind time:       1.27s
Check time:      8.17s
Total time:     14.43s

With the shims always used:

Memory used:   835746K
Parse time:      5.34s
Bind time:       1.63s
Check time:     11.22s
Total time:     18.19s

Memory used:   820061K
Parse time:      5.40s
Bind time:       1.57s
Check time:     11.30s
Total time:     18.28s

Memory used:   830217K
Parse time:      5.41s
Bind time:       1.58s
Check time:     11.22s
Total time:     18.20s

I have created a new PR #11210 which fixes this issue.

@ghost ghost closed this Sep 28, 2016
@mhegazy mhegazy deleted the map branch November 2, 2017 21:05
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants