16:13
<Mathieu Hofman>
I've used https://nodejs.org/download/v8-canary/ successfully before
16:14
<Mathieu Hofman>
Built from https://github.com/nodejs/node-v8
20:29
<rbuckton>
Built from https://github.com/nodejs/node-v8
Thanks! This works perfectly
20:32
<rbuckton>
instanceof for Mutex/Condition/SharedArray is great. I see that it works for instances of instances of SharedStructType as well, though there's still no fast way to see if a value is any shared struct (i.e., without access to its specific constructor)
20:33
<shu>
rbuckton: there is, i also added SharedStructType.isSharedStruct iirc
20:35
<rbuckton>
Ah, great
20:41
<rbuckton>
Hmm. I was hoping I could use SharedStructType to emulate SharedArray when I also need extra fields, but its significantly slower so that's a no-go.
20:44
<shu>
yes -- that's a possible optimization that's not implemented due to complexity/effort
20:44
<shu>
if you use indexed fields in SharedStructTypes, those are always backed by "dictionary elements", i.e. a hash table
20:44
<shu>
SharedArrays are contiguous arrays
20:45
<shu>
we can optimize SharedStructTypes to use fast elements when those indexes are all packed, or something
20:45
<shu>
i could put it on the queue if it's a blocker
20:47
<Ashley Claymore>
Hmm. I was hoping I could use SharedStructType to emulate SharedArray when I also need extra fields, but its significantly slower so that's a no-go.
Could the N extra fields be hidden at the start of the sharedarray? Their names map to fixed indexes 0,1,2 etc, and all array looping logic knows to start index at N? Or too big a refactor?
20:48
<rbuckton>
Thats just as much of a refactor as what I was doing, which was stashing a SharedArray in an items field in another struct. The biggest issue with that approach is that every function that expected a NodeArray with indexable elements has to check if it's instead a SharedNodeArray to use its items field.
20:49
<shu>
rbuckton: what's the full list of field names you'd like to be fast?
20:49
<shu>
might not be too bad, i'll see if i have time next week
20:55
<rbuckton>

I'm not sure how to answer that. What's "slow" is that I'm trying to emulate a SharedArray with fields named "length", "0", "1", etc. as well as attach a few extra fields that we normally stash on a NodeArray, which looks something like this:

interface NodeArray<T extends Node> extends Array<T> {
  pos: number;
  end: number;
  hasTrailingComma: boolean;
  transformFlags: TransformFlags; // number
}

If you're asking about other fields, the most frequently hit fields on our AST are pos, end, kind, id, transformFlags, and parent:

interface Node {
  pos: number;
  end: number;
  kind: SyntaxKind; // number
  transformFlags: TransformFlags; // number
  id: number | undefined;
  parent: Node | undefined;
}
20:59
<shu>
ah i see
20:59
<shu>
is the length of these nodes known AOT per Node?
20:59
<shu>
(and are contiguous?)
21:07
<rbuckton>
Can you clarify what you mean by contiguous?
21:09
<rbuckton>
I've essentially mirrored our AST structure into shared struct definitions, so I could tell you exactly how many fields are attached to a given node, though I'd need a bit if you want something like the average field count.
21:13
<shu>
by contiguous i mean if a node type's length is N, then the node always has indexed properties 0 to N-1, inclusive, with no holes
21:13
<shu>
hole in the usual JS sense
21:14
<shu>
and no, not looking for an average field count
21:14
<shu>
by AOT i mean is the length fixed per node type instead of per node instance
21:14
<shu>
since all shared arrays are fixed length
21:14
<rbuckton>
A Node? No. A NodeArray, yes. There are no holes in NodeArrays, though they could be filled with different kinds of Node subtypes.
21:15
<shu>
oh, my bad, i think i misread
21:15
<shu>
you're not saying you want Nodes to have some elements in addition to some properties
21:16
<shu>
you're saying you're trying to convert NodeArrays, which are arrays + some string-named properties that you listed above
21:16
<shu>
that points to another direction, which is...
21:17
<shu>
perhaps the dev trial should unify the notions of SharedStructType and SharedArray and just let SharedStructTypes specify "i want N indexed properties"
21:17
<shu>
but even then a SharedArray constructor is probably helpful
21:18
<shu>
in any case i hear the feedback now and i'll push it on the queue
21:21
<rbuckton>

Yes. I have two choices for a shared struct implementation of a NodeArray:

  1. I use a Shared Struct with a small set of string-named fields (like pos/end), as well a length and a number of indexed fields with no holes. This would emulate NodeArray except for functionality from array prototype as I can just use length and indices instead. This provides enough overlap between NodeArray and SharedNodeArray that I don't need to special case every single function that works with NodeArray.

  2. I use a Shared Struct with the same set of string-named fields as well as an items field that holds a SharedArray. In this case, I need to add branching cases in every function that works with NodeArray.

21:23
<shu>
i'll try to allow (1) to be more easily expressed and be faster
21:23
<rbuckton>
Another option would be the ability to add extra fields to a SharedArray, such that integer indexed properties go through the current fast path for SharedArray and other string properties go the slow path.
21:23
<rbuckton>
Though I assume that could be handled by unification as you suggested above.
21:23
<shu>
something like SharedStructType(fields, { alsoGiveMeElementsUpTo: N }) or whatever
21:25
<rbuckton>
Yeah, or the SharedStructType constructor could just test fields for interger-indexed field names that start from 0 and go to N with no holes, and optimize those (unless you need to optimize length as well).
21:26
<rbuckton>
For the purposes of the trial, I don't necessarily need convenience, I just need capability. I can work around inconveniences if the capabilities are there.
21:48
<rbuckton>
Quick update on the parallel parsing front, after tinkering with how I batch source files to send to background threads, I went from parse time being 6x slower than single threaded, to only 1.5x slower.
21:49
<shu>
ah interesting, would love to dig in at some point, should be faster after all :)
21:56
<rbuckton>
TypeScript normally does a depth-first parse of source files: for each root file, we parse the file, collect its imports and /// <reference> directives, and then parse those files. The order in which we parse files affects signature overload resolution when we merge types for global scope and module augmentations. Depth first isn't very efficient for parallelization though, so I'm having to rewrite it to be breadth-first instead, which will (of course) affect overload resolution. I was trying a batching approach to minimize that affect, but it wasn't successful. In the end I'm probably just going to "fix it in post" and reorder the file list based on what we would have generated prior to batching.
22:04
<Ashley Claymore>
Curious, Is some of the remaining slowdown coming from under utilization, threads waiting for work to do, or are they fully saturated but there is additional overhead with the sharing? (Very excited by all this, we've also been looking at running TS in parallel and the parsing was showing as a bottleneck due to cache misses. A cross thread cache could be a big win)
22:06
<rbuckton>
I don't have enough information on that to say, yet. I think some of the inefficiencies are due to workarounds and needing to convert the struct representation to a normal Node representation.
22:07
<rbuckton>
I'm currently working on abstracting away the differences between a Node and a SharedNode so that I can just use shared structs end to end in the command line compiler, which would at least do away with the conversion step.
22:09
<rbuckton>
Once that works, I can look into whether its feasible to bind in parallel and possibly even emit in parallel. Unfortunately our emitter often queries information from the checker, which we probably won't be able to parallelize currently.
22:10
<rbuckton>
And I'm not sure how efficient synchronizing on the checker and calling into it from other threads will be.
22:14
<rbuckton>
if you use indexed fields in SharedStructTypes, those are always backed by "dictionary elements", i.e. a hash table
Are you saying all property access against a shared struct (not a shared array) in the origin trial uses hash table lookup/slow mode?
22:15
<shu>
Are you saying all property access against a shared struct (not a shared array) in the origin trial uses hash table lookup/slow mode?
No, just the integer-indexed properties on shared structs
22:15
<shu>
string-named properties are fast
22:15
<rbuckton>
Ah, ok
22:16
<shu>
it's a pecularity of how elements (indexed properties) are stored on JSObjects