Ejemplo n.º 1
0
        public PartitionedSnapshotWindowStartEdgePipe(
            SnapshotWindowStreamable <TKey, TInput, TState, TOutput> stream,
            IStreamObserver <TKey, TOutput> observer)
            : base(stream, observer)
        {
            this.aggregate         = stream.Aggregate;
            this.initialStateExpr  = this.aggregate.InitialState();
            this.initialState      = this.initialStateExpr.Compile();
            this.accumulateExpr    = this.aggregate.Accumulate();
            this.accumulate        = this.accumulateExpr.Compile();
            this.computeResultExpr = this.aggregate.ComputeResult();
            this.computeResult     = this.computeResultExpr.Compile();

            var comparer = stream.Properties.KeyEqualityComparer;

            this.keyComparerEqualsExpr      = comparer.GetEqualsExpr();
            this.keyComparerEquals          = this.keyComparerEqualsExpr.Compile();
            this.keyComparerGetHashCodeExpr = comparer.GetGetHashCodeExpr();
            this.keyComparerGetHashCode     = this.keyComparerGetHashCodeExpr.Compile();

            this.errorMessages = stream.ErrorMessages;
            this.pool          = MemoryManager.GetMemoryPool <TKey, TOutput>(false);
            this.pool.Get(out this.batch);
            this.batch.Allocate();

            var generator = comparer.CreateFastDictionary2Generator <TKey, HeldState <TState> >(1, this.keyComparerEquals, this.keyComparerGetHashCode, stream.Properties.QueryContainer);

            this.aggregateByKey = generator.Invoke();
        }
Ejemplo n.º 2
0
        public PartitionedSnapshotWindowHoppingPipe(
            SnapshotWindowStreamable <TKey, TInput, TState, TOutput> stream,
            IStreamObserver <TKey, TOutput> observer)
            : base(stream, observer)
        {
            this.aggregate         = stream.Aggregate;
            this.initialStateExpr  = this.aggregate.InitialState();
            this.initialState      = this.initialStateExpr.Compile();
            this.accumulateExpr    = this.aggregate.Accumulate();
            this.accumulate        = this.accumulateExpr.Compile();
            this.deaccumulateExpr  = this.aggregate.Deaccumulate();
            this.deaccumulate      = this.deaccumulateExpr.Compile();
            this.differenceExpr    = this.aggregate.Difference();
            this.difference        = this.differenceExpr.Compile();
            this.computeResultExpr = this.aggregate.ComputeResult();
            this.computeResult     = this.computeResultExpr.Compile();

            var comparer = stream.Properties.KeyEqualityComparer;

            this.keyComparerEqualsExpr      = comparer.GetEqualsExpr();
            this.keyComparerEquals          = this.keyComparerEqualsExpr.Compile();
            this.keyComparerGetHashCodeExpr = comparer.GetGetHashCodeExpr();
            this.keyComparerGetHashCode     = this.keyComparerGetHashCodeExpr.Compile();

            this.errorMessages = stream.ErrorMessages;
            this.pool          = MemoryManager.GetMemoryPool <TKey, TOutput>(false);
            this.pool.Get(out this.batch);
            this.batch.Allocate();

            this.aggregateByKey = comparer.CreateFastDictionary2Generator <TKey, HeldState <TState> >(1, this.keyComparerEquals, this.keyComparerGetHashCode, stream.Properties.QueryContainer).Invoke();
            var stateDictGenerator = comparer.CreateFastDictionaryGenerator <TKey, StateAndActive <TState> >(1, this.keyComparerEquals, this.keyComparerGetHashCode, stream.Properties.QueryContainer);

            this.ecqEntryPool    = new DataStructurePool <FastDictionary <TKey, StateAndActive <TState> > >(() => stateDictGenerator.Invoke());
            this.hopsPerDuration = (int)(stream.Source.Properties.ConstantDurationLength.Value / stream.Source.Properties.ConstantHopLength) + 1;
        }
        public SnapshotWindowHoppingPipeSimple(
            SnapshotWindowStreamable <Empty, TInput, TState, TOutput> stream,
            IStreamObserver <Empty, TOutput> observer)
            : base(stream, observer)
        {
            this.aggregate         = stream.Aggregate;
            this.initialStateExpr  = this.aggregate.InitialState();
            this.initialState      = this.initialStateExpr.Compile();
            this.accumulateExpr    = this.aggregate.Accumulate();
            this.accumulate        = this.accumulateExpr.Compile();
            this.deaccumulateExpr  = this.aggregate.Deaccumulate();
            this.deaccumulate      = this.deaccumulateExpr.Compile();
            this.differenceExpr    = this.aggregate.Difference();
            this.difference        = this.differenceExpr.Compile();
            this.computeResultExpr = this.aggregate.ComputeResult();
            this.computeResult     = this.computeResultExpr.Compile();

            this.errorMessages = stream.ErrorMessages;
            this.pool          = MemoryManager.GetMemoryPool <Empty, TOutput>(false);
            this.pool.Get(out this.batch);
            this.batch.Allocate();

            var hopsPerDuration = (int)(stream.Source.Properties.ConstantDurationLength.Value / stream.Source.Properties.ConstantHopLength) + 1;

            this.ecq = new CircularBuffer <HeldState <TState> >(hopsPerDuration);
        }
        public SnapshotWindowStartEdgePipeSimple(
            SnapshotWindowStreamable <Empty, TInput, TState, TOutput> stream,
            IStreamObserver <Empty, TOutput> observer)
            : base(stream, observer)
        {
            this.aggregate         = stream.Aggregate;
            this.initialStateExpr  = this.aggregate.InitialState();
            this.initialState      = this.initialStateExpr.Compile();
            this.accumulateExpr    = this.aggregate.Accumulate();
            this.accumulate        = this.accumulateExpr.Compile();
            this.computeResultExpr = this.aggregate.ComputeResult();
            this.computeResult     = this.computeResultExpr.Compile();

            this.errorMessages = stream.ErrorMessages;
            this.pool          = MemoryManager.GetMemoryPool <Empty, TOutput>(false);
            this.pool.Get(out this.batch);
            this.batch.Allocate();
        }
        public PartitionedSnapshotWindowTumblingPipeSimple(
            SnapshotWindowStreamable <PartitionKey <TPartitionKey>, TInput, TState, TOutput> stream,
            IStreamObserver <PartitionKey <TPartitionKey>, TOutput> observer, long hop)
            : base(stream, observer)
        {
            this.aggregate         = stream.Aggregate;
            this.initialStateExpr  = this.aggregate.InitialState();
            this.initialState      = this.initialStateExpr.Compile();
            this.accumulateExpr    = this.aggregate.Accumulate();
            this.accumulate        = this.accumulateExpr.Compile();
            this.computeResultExpr = this.aggregate.ComputeResult();
            this.computeResult     = this.computeResultExpr.Compile();

            this.errorMessages = stream.ErrorMessages;
            this.pool          = MemoryManager.GetMemoryPool <PartitionKey <TPartitionKey>, TOutput>(false);
            this.pool.Get(out this.batch);
            this.batch.Allocate();

            this.hop = hop;
        }
Ejemplo n.º 6
0
        public SnapshotWindowSlidingPipeSimple(
            SnapshotWindowStreamable <Empty, TInput, TState, TOutput> stream,
            IStreamObserver <Empty, TOutput> observer)
            : base(stream, observer)
        {
            this.aggregate         = stream.Aggregate;
            this.initialStateExpr  = this.aggregate.InitialState();
            this.initialState      = this.initialStateExpr.Compile();
            this.accumulateExpr    = this.aggregate.Accumulate();
            this.accumulate        = this.accumulateExpr.Compile();
            this.deaccumulateExpr  = this.aggregate.Deaccumulate();
            this.deaccumulate      = this.deaccumulateExpr.Compile();
            this.differenceExpr    = this.aggregate.Difference();
            this.difference        = this.differenceExpr.Compile();
            this.computeResultExpr = this.aggregate.ComputeResult();
            this.computeResult     = this.computeResultExpr.Compile();

            this.errorMessages = stream.ErrorMessages;
            this.pool          = MemoryManager.GetMemoryPool <Empty, TOutput>(false);
            this.pool.Get(out this.batch);
            this.batch.Allocate();

            this.ecq = new ElasticCircularBuffer <HeldState <TState> >();
        }
Ejemplo n.º 7
0
        public static Tuple <Type, string> Generate <TKey, TInput, TState, TOutput>(SnapshotWindowStreamable <TKey, TInput, TState, TOutput> stream, AggregatePipeType pipeType)
        {
            Contract.Requires(stream != null);
            Contract.Ensures(Contract.Result <Tuple <Type, string> >() == null || typeof(IStreamObserver <TKey, TInput>).GetTypeInfo().IsAssignableFrom(Contract.Result <Tuple <Type, string> >().Item1));

            var             container = stream.Properties.QueryContainer;
            string          generatedClassName;
            string          expandedCode;
            List <Assembly> assemblyReferences;
            string          errorMessages = null;

            try
            {
                AggregateTemplate template;
                switch (pipeType)
                {
                case AggregatePipeType.StartEdge:
                    template = new SnapshotWindowStartEdgeTemplate();
                    break;

                case AggregatePipeType.PriorityQueue:
                    template = new SnapshotWindowPriorityQueueTemplate();
                    break;

                case AggregatePipeType.Tumbling:
                    template = new SnapshotWindowTumblingTemplate();
                    break;

                case AggregatePipeType.Sliding:
                    template = new SnapshotWindowSlidingTemplate();
                    break;

                case AggregatePipeType.Hopping:
                    template = new SnapshotWindowHoppingTemplate
                    {
                        hopsPerDuration = ((int)(stream.Source.Properties.ConstantDurationLength.Value / stream.Source.Properties.ConstantHopLength) + 1).ToString()
                    };
                    break;

                default:
                    Contract.Assert(false, "case meant to be exhaustive");
                    throw new InvalidOperationException("case meant to be exhaustive");
                }

                template.isUngrouped = (typeof(TKey) == typeof(Empty));
                var keyType    = template.keyType = typeof(TKey);
                var inputType  = template.inputType = typeof(TInput);
                var stateType  = template.stateType = typeof(TState);
                var outputType = template.outputType = typeof(TOutput);

                template.inputFields = new ColumnarRepresentation(inputType).AllFields;

                template.outputFields = new ColumnarRepresentation(outputType).AllFields;

                assemblyReferences = new List <Assembly>();

                #region Key Comparer
                IEqualityComparerExpression <TKey> keyComparer;
                keyComparer = stream.Properties.KeyEqualityComparer;
                var equalsExpression      = keyComparer.GetEqualsExpr();
                var getHashcodeExpression = keyComparer.GetGetHashCodeExpr();
                template.inlinedKeyComparerEquals =
                    (left, right) =>
                    string.Format("({0})", equalsExpression.Inline(left, right));
                template.inlinedKeyComparerGetHashCode =
                    (x) =>
                    string.Format("({0}/* inlined GetHashCode */)", getHashcodeExpression.Inline(x));
                if (keyType.IsAnonymousType())
                {
                    template.inlinedKeyComparerEquals =
                        (left, right) => string.Format("keyComparerEquals({0}, {1})", left, right);
                    template.inlinedKeyComparerGetHashCode =
                        (x) => string.Format("keyComparerGetHashCode({0})", x);
                }
                assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(equalsExpression));
                assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(getHashcodeExpression));
                #endregion

                #region Aggregate Functions
                var initialStateLambda = stream.Aggregate.InitialState();
                if (ConstantExpressionFinder.IsClosedExpression(initialStateLambda))
                {
                    template.initialState = initialStateLambda.Body.ExpressionToCSharp();
                    assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(initialStateLambda));
                }
                else
                {
                    if (Config.CodegenOptions.SuperStrictColumnar)
                    {
                        errorMessages = "Code Generation for Aggregate: couldn't inline the initial state lambda!";
                        throw new InvalidOperationException(errorMessages);
                    }
                    else
                    {
                        template.useCompiledInitialState = true;
                        template.initialState            = "initialState()";
                    }
                }

                var accumulateLambda = stream.Aggregate.Accumulate();
                if (ConstantExpressionFinder.IsClosedExpression(accumulateLambda))
                {
                    var accTransformedLambda = Extensions.TransformFunction <TKey, TInput>(accumulateLambda, 2);
                    template.accumulate = (stateArg, longArg) => accTransformedLambda.Inline(stateArg, longArg);
                    assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(accumulateLambda));
                }
                else
                {
                    if (Config.CodegenOptions.SuperStrictColumnar)
                    {
                        errorMessages = "Code Generation for Aggregate: couldn't inline the accumulate lambda!";
                        throw new InvalidOperationException(errorMessages);
                    }
                    else
                    {
                        template.useCompiledAccumulate = true;
                        template.accumulate            = (s1, s2) => string.Format("accumulate({0}, {1}, batch[i]);", s1, s2);
                    }
                }

                var deaccumulateLambda = stream.Aggregate.Deaccumulate();
                if (ConstantExpressionFinder.IsClosedExpression(deaccumulateLambda))
                {
                    var deaccumulateTransformedLambda = Extensions.TransformFunction <TKey, TInput>(deaccumulateLambda, 2);
                    template.deaccumulate = (stateArg, longArg) => deaccumulateTransformedLambda.Inline(stateArg, longArg);
                    assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(deaccumulateLambda));
                }
                else
                {
                    if (Config.CodegenOptions.SuperStrictColumnar)
                    {
                        errorMessages = "Code Generation for Aggregate: couldn't inline the deaccumulate lambda!";
                        throw new InvalidOperationException(errorMessages);
                    }
                    else
                    {
                        template.useCompiledDeaccumulate = true;
                        template.deaccumulate            = (s1, s2) => string.Format("deaccumulate({0}, {1}, batch[i]);", s1, s2);
                    }
                }

                var differenceLambda = stream.Aggregate.Difference();
                if (ConstantExpressionFinder.IsClosedExpression(differenceLambda))
                {
                    template.difference = (stateArg1, stateArg2) => differenceLambda.Inline(stateArg1, stateArg2);
                    assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(differenceLambda));
                }
                else
                {
                    if (Config.CodegenOptions.SuperStrictColumnar)
                    {
                        errorMessages = "Code Generation for Aggregate: couldn't inline the difference lambda!";
                        throw new InvalidOperationException(errorMessages);
                    }
                    else
                    {
                        template.useCompiledDifference = true;
                        template.difference            = (s1, s2) => string.Format("difference({0}, {1});", s1, s2);
                    }
                }

                var computeResultLambda = stream.Aggregate.ComputeResult();
                if (ConstantExpressionFinder.IsClosedExpression(computeResultLambda))
                {
                    if (outputType.IsAnonymousType())
                    {
                        if (computeResultLambda.Body is NewExpression newExpression)
                        {
                            var outputBatchType = StreamMessageManager.GetStreamMessageType <TKey, TOutput>();
                            var foo             = Transform(newExpression, outputBatchType);
                            template.computeResult = (stateArg) => Expression.Lambda(foo, computeResultLambda.Parameters.ToArray()).Inline(stateArg);
                        }
                        else
                        {
                            template.computeResult = (stateArg) => computeResultLambda.Inline(stateArg);
                        }
                    }
                    else
                    {
                        template.computeResult = (stateArg) => computeResultLambda.Inline(stateArg);
                    }
                    assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(computeResultLambda));
                }
                else
                {
                    if (Config.CodegenOptions.SuperStrictColumnar || outputType.IsAnonymousType())
                    {
                        // second disjunct is because if we aren't inlining the computeResult function and
                        // the output type is anonymous, calling the compiled computeResult function returns
                        // a value of the anonymous type and since the generated operator represents the anonymous
                        // type as a generic parameter, it can't use the "field" (i.e., property) names to
                        // get the individual pieces to assign to each column of the output message.
                        errorMessages = "Code Generation for Aggregate: couldn't inline the compute result lambda!";
                        throw new InvalidOperationException(errorMessages);
                    }
                    else
                    {
                        template.useCompiledComputeResult = true;
                        template.computeResult            = (stateArg) => "computeResult(" + stateArg + ");";
                    }
                }
                #endregion

                generatedClassName = template.className = string.Format("Aggregate_{0}", sequenceNumber++);
                generatedClassName = generatedClassName.AddNumberOfNecessaryGenericArguments(keyType, inputType, stateType, outputType);

                template.staticCtor = Transformer.StaticCtor(template.className);
                expandedCode        = template.TransformText();

                assemblyReferences.AddRange(Transformer.AssemblyReferencesNeededFor(typeof(TKey), typeof(TInput), typeof(TState), typeof(TOutput), typeof(FastDictionaryGenerator), typeof(SortedDictionary <,>)));
                assemblyReferences.Add(typeof(IStreamable <,>).GetTypeInfo().Assembly);
                assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TInput>());
                assemblyReferences.Add(Transformer.GeneratedStreamMessageAssembly <TKey, TOutput>());
                assemblyReferences.Add(Transformer.GeneratedMemoryPoolAssembly <TKey, TOutput>());
                if (container != null)
                {
                    assemblyReferences.AddRange(container.CollectedGeneratedTypes.Select(o => o.GetTypeInfo().Assembly));
                }

                var a = Transformer.CompileSourceCode(expandedCode, assemblyReferences, out errorMessages);
                if (keyType.IsAnonymousType())
                {
                    if (errorMessages == null)
                    {
                        errorMessages = string.Empty;
                    }
                    errorMessages += "\nCodegen Warning: The key type for an aggregate is an anonymous type (or contains an anonymous type), preventing the inlining of the key equality and hashcode functions. This may lead to poor performance.\n";
                }
                var t = a.GetType(generatedClassName);
                if (t.GetTypeInfo().IsGenericType)
                {
                    var list = typeof(TKey).GetAnonymousTypes();
                    list.AddRange(typeof(TInput).GetAnonymousTypes());
                    list.AddRange(typeof(TState).GetAnonymousTypes());
                    list.AddRange(typeof(TOutput).GetAnonymousTypes());
                    t = t.MakeGenericType(list.ToArray());
                }
                return(Tuple.Create(t, errorMessages));
            }
            catch
            {
                if (Config.CodegenOptions.DontFallBackToRowBasedExecution)
                {
                    throw new InvalidOperationException("Code Generation failed when it wasn't supposed to!");
                }
                return(Tuple.Create((Type)null, errorMessages));
            }
        }