예제 #1
0
        private void SealNodeForBulkIncomingEdgeAddition(NodeId target)
        {
            BufferPointer <NodeEdgeListHeader> targetInEdges = InEdges.GetBufferPointer(target.Value);

            targetInEdges.Buffer[targetInEdges.Index].Seal();
            Contract.Assert(targetInEdges.Buffer[targetInEdges.Index].IsSealed, "Node should be sealed");
        }
예제 #2
0
        private void AddEdges(NodeId target, HashSet <Edge> incomingEdges)
        {
            BufferPointer <NodeEdgeListHeader> targetInEdges = InEdges.GetBufferPointer(target.Value);

            Contract.Assert(targetInEdges.Buffer[targetInEdges.Index].IsSealed, "Bulk additions can only be made to sealed nodes");

            using (m_globalLock.AcquireReadLock())
            {
                Contract.Assert(m_state == MutableGraphState.Mutating, "Graph mutations are not permitted after sealing");

                foreach (var incoming in incomingEdges)
                {
                    var source       = incoming.OtherNode;
                    var incomingLock = m_locks[GetLockNumber(source.Value)];
                    using (AcquireLockForState(incomingLock, MutableGraphState.Mutating))
                    {
                        // AddEdgeUnchecked is thread-safe with respect to concurrent modifications
                        AddEdgeUnchecked(
                            source: source,
                            target: target,
                            targetInEdges: targetInEdges,
                            isLight: incoming.IsLight,
                            bulkAddingTargetIncoming: true);
                    }
                }

                Interlocked.Increment(ref m_modificationsSinceLastNodeHeightComputation);
            }
        }
예제 #3
0
        private bool AddEdgeUnchecked(NodeId source, NodeId target, bool isLight)
        {
            BufferPointer <NodeEdgeListHeader> targetInEdges = InEdges.GetBufferPointer(target.Value);

            Contract.Assert(!targetInEdges.Buffer[targetInEdges.Index].IsSealed, "Attempted to add edge to sealed node");

            return(AddEdgeUnchecked(
                       source: source,
                       target: target,
                       targetInEdges: targetInEdges,
                       isLight: isLight,
                       bulkAddingTargetIncoming: false));
        }
예제 #4
0
        private bool IsSealed(NodeId target)
        {
            BufferPointer <NodeEdgeListHeader> targetInEdges = InEdges.GetBufferPointer(target.Value);

            return(targetInEdges.Buffer[targetInEdges.Index].IsSealed);
        }
예제 #5
0
        /// <summary>
        /// Loads this graph from a given binary stream.
        /// </summary>
        private void Load(BuildXLReader reader)
        {
            m_lastNodeId = (int)reader.ReadUInt32();
            m_edgeCount  = reader.ReadInt32();
            Contract.Assume(m_lastNodeId <= NodeId.MaxValue);

            // Create buffer with space for in edges and out edges
            m_edgeBuffer.Initialize(m_edgeCount * 2);
            int edgeIndex = 0;

            // Read the out edges
            {
                var accessor = m_edgeBuffer.GetAccessor();

                // TODO: This loop takes 70% of the deserialization time; make faster.
                for (uint i = 1; i <= m_lastNodeId; ++i)
                {
                    int outNodeCount   = reader.ReadInt32Compact();
                    int startEdgeIndex = edgeIndex;
                    for (int j = 0; j < outNodeCount; ++j)
                    {
                        var outgoingEdge = Edge.Deserialize(reader);
                        accessor[edgeIndex] = outgoingEdge;
                        edgeIndex++;
                    }

                    OutEdges[i] = new NodeEdgeListHeader(startEdgeIndex, outNodeCount);
                }
            }

            // Read the count of in edges
            // TODO: This loop takes 10% of the deserialization time; make faster.
            for (uint i = 1; i <= m_lastNodeId; i++)
            {
                int nodeHeight = reader.ReadInt32Compact();
                NodeHeights[i] = nodeHeight;

                int inEdgeCount = reader.ReadInt32Compact();

                // first edge index starts at end of edge span for this node and is decrements as edges
                // are discovered and added below. At the end the first edge index will
                // be at the beginning of the span
                edgeIndex += inEdgeCount;
                InEdges[i] = new NodeEdgeListHeader(edgeIndex, inEdgeCount);
            }

            // Write each out edge set to graph and compute the in edges
            // TODO: This parallel loop takes 20% of the (sequential) deserialization time; make faster.
            Parallel.For(1, m_lastNodeId + 1,
                         (i) =>
            {
                NodeId node  = new NodeId((uint)i);
                var accessor = m_edgeBuffer.GetAccessor();
                foreach (var e in GetOutgoingEdges(node))
                {
                    var inEdge = new Edge(node, e.IsLight);

                    // Note: We access the InEdges array element directly, not via the ConcurrentDenseIndex's indexer property.
                    // As a result, we mutate the actual array element, instead of a copy.
                    var p     = InEdges.GetBufferPointer(e.OtherNode.Value);
                    var index = p.Buffer[p.Index].InterlockedDecrementFirstIndex();

                    // Set the prior index and point header at that index. The initial value
                    // to index should be set to the index after the span. So this will always
                    // set an index within the edge span
                    accessor[index] = inEdge;
                }
            });
        }