Example #1
0
        public static void EncodePgoData <TType>(IEnumerable <PgoSchemaElem> schemas, IPgoEncodedValueEmitter <TType> valueEmitter, bool emitAllElementsUnconditionally)
        {
            PgoSchemaElem prevSchema         = default(PgoSchemaElem);
            TType         prevEmittedType    = default(TType);
            long          prevEmittedIntData = 0;

            foreach (PgoSchemaElem schema in schemas)
            {
                int ilOffsetDiff = schema.ILOffset - prevSchema.ILOffset;
                int OtherDiff    = schema.Other - prevSchema.Other;
                int CountDiff    = schema.Count - prevSchema.Count;
                int TypeDiff     = (int)schema.InstrumentationKind - (int)prevSchema.InstrumentationKind;

                InstrumentationDataProcessingState modifyMask = (InstrumentationDataProcessingState)0;

                if (!emitAllElementsUnconditionally)
                {
                    if (ilOffsetDiff != 0)
                    {
                        modifyMask = modifyMask | InstrumentationDataProcessingState.ILOffset;
                    }
                    if (TypeDiff != 0)
                    {
                        modifyMask = modifyMask | InstrumentationDataProcessingState.Type;
                    }
                    if (CountDiff != 0)
                    {
                        modifyMask = modifyMask | InstrumentationDataProcessingState.Count;
                    }
                    if (OtherDiff != 0)
                    {
                        modifyMask = modifyMask | InstrumentationDataProcessingState.Other;
                    }
                }
                else
                {
                    modifyMask = InstrumentationDataProcessingState.ILOffset |
                                 InstrumentationDataProcessingState.Type |
                                 InstrumentationDataProcessingState.Count |
                                 InstrumentationDataProcessingState.Other;
                }

                Debug.Assert(modifyMask != InstrumentationDataProcessingState.Done);

                valueEmitter.EmitLong((long)modifyMask, 0);

                if ((modifyMask & InstrumentationDataProcessingState.ILOffset) == InstrumentationDataProcessingState.ILOffset)
                {
                    valueEmitter.EmitLong(schema.ILOffset, prevSchema.ILOffset);
                }
                if ((modifyMask & InstrumentationDataProcessingState.Type) == InstrumentationDataProcessingState.Type)
                {
                    valueEmitter.EmitLong((long)schema.InstrumentationKind, (long)prevSchema.InstrumentationKind);
                }
                if ((modifyMask & InstrumentationDataProcessingState.Count) == InstrumentationDataProcessingState.Count)
                {
                    valueEmitter.EmitLong(schema.Count, prevSchema.Count);
                }
                if ((modifyMask & InstrumentationDataProcessingState.Other) == InstrumentationDataProcessingState.Other)
                {
                    valueEmitter.EmitLong(schema.Other, prevSchema.Other);
                }

                for (int i = 0; i < schema.Count; i++)
                {
                    switch (schema.InstrumentationKind & PgoInstrumentationKind.MarshalMask)
                    {
                    case PgoInstrumentationKind.None:
                        break;

                    case PgoInstrumentationKind.FourByte:
                    {
                        long valueToEmit;
                        if (schema.Count == 1)
                        {
                            valueToEmit = schema.DataLong;
                        }
                        else
                        {
                            valueToEmit = ((int[])schema.DataObject)[i];
                        }
                        valueEmitter.EmitLong(valueToEmit, prevEmittedIntData);
                        prevEmittedIntData = valueToEmit;
                        break;
                    }

                    case PgoInstrumentationKind.EightByte:
                    {
                        long valueToEmit;
                        if (schema.Count == 1)
                        {
                            valueToEmit = schema.DataLong;
                        }
                        else
                        {
                            valueToEmit = ((long[])schema.DataObject)[i];
                        }
                        valueEmitter.EmitLong(valueToEmit, prevEmittedIntData);
                        prevEmittedIntData = valueToEmit;
                        break;
                    }

                    case PgoInstrumentationKind.TypeHandle:
                    {
                        TType typeToEmit = ((TType[])schema.DataObject)[i];
                        valueEmitter.EmitType(typeToEmit, prevEmittedType);
                        prevEmittedType = typeToEmit;
                        break;
                    }
                    }
                }

                prevSchema = schema;
            }

            // Emit a "done" schema
            if (!valueEmitter.EmitDone())
            {
                // If EmitDone returns true, no further data needs to be encoded.
                // Otherwise, emit a "Done" schema
                valueEmitter.EmitLong((long)InstrumentationDataProcessingState.Type, 0);
                valueEmitter.EmitLong((long)PgoInstrumentationKind.Done, (long)prevSchema.InstrumentationKind);
            }
        }
Example #2
0
        public static PgoSchemaElem[] Merge <TType>(ReadOnlySpan <PgoSchemaElem[]> schemasToMerge)
        {
            {
                // The merging algorithm will sort the schema data by iloffset, then by InstrumentationKind
                // From there each individual instrumentation kind shall have a specific merging rule
                Dictionary <PgoSchemaElem, PgoSchemaElem> dataMerger = new Dictionary <PgoSchemaElem, PgoSchemaElem>(PgoSchemaMergeComparer.Singleton);

                foreach (PgoSchemaElem[] schemaSet in schemasToMerge)
                {
                    bool foundNumRuns = false;

                    foreach (PgoSchemaElem schema in schemaSet)
                    {
                        if (schema.InstrumentationKind == PgoInstrumentationKind.NumRuns)
                        {
                            foundNumRuns = true;
                        }
                        MergeInSchemaElem(dataMerger, schema);
                    }

                    if (!foundNumRuns)
                    {
                        PgoSchemaElem oneRunSchema = new PgoSchemaElem();
                        oneRunSchema.InstrumentationKind = PgoInstrumentationKind.NumRuns;
                        oneRunSchema.ILOffset            = 0;
                        oneRunSchema.Other = 1;
                        oneRunSchema.Count = 1;
                        MergeInSchemaElem(dataMerger, oneRunSchema);
                    }
                }

                PgoSchemaElem[] result = new PgoSchemaElem[dataMerger.Count];
                dataMerger.Values.CopyTo(result, 0);
                Array.Sort(result, PgoSchemaMergeComparer.Singleton);
                return(result);
            }

            void MergeInSchemaElem(Dictionary <PgoSchemaElem, PgoSchemaElem> dataMerger, PgoSchemaElem schema)
            {
                long sortKey = ((long)schema.ILOffset) << 32 | (long)schema.InstrumentationKind;

                if (dataMerger.TryGetValue(schema, out var existingSchemaItem))
                {
                    // Actually merge two schema items
                    PgoSchemaElem mergedElem = existingSchemaItem;

                    switch (existingSchemaItem.InstrumentationKind)
                    {
                    case PgoInstrumentationKind.BasicBlockIntCount:
                    case PgoInstrumentationKind.TypeHandleHistogramCount:
                        if ((existingSchemaItem.Count != 1) || (schema.Count != 1))
                        {
                            throw new Exception("Unable to merge pgo data. Invalid format");
                        }
                        mergedElem.DataLong = existingSchemaItem.DataLong + schema.DataLong;
                        break;

                    case PgoInstrumentationKind.TypeHandleHistogramTypeHandle:
                    {
                        mergedElem.Count = existingSchemaItem.Count + schema.Count;
                        TType[] newMergedTypeArray = new TType[mergedElem.Count];
                        mergedElem.DataObject = newMergedTypeArray;
                        int i = 0;
                        foreach (TType type in (TType[])existingSchemaItem.DataObject)
                        {
                            newMergedTypeArray[i++] = type;
                        }
                        foreach (TType type in (TType[])schema.DataObject)
                        {
                            newMergedTypeArray[i++] = type;
                        }
                        break;
                    }

                    case PgoInstrumentationKind.Version:
                    {
                        mergedElem.Other = Math.Max(existingSchemaItem.Other, schema.Other);
                        break;
                    }

                    case PgoInstrumentationKind.NumRuns:
                    {
                        mergedElem.Other = existingSchemaItem.Other + schema.Other;
                        break;
                    }
                    }

                    Debug.Assert(PgoSchemaMergeComparer.Singleton.Compare(schema, mergedElem) == 0);
                    Debug.Assert(PgoSchemaMergeComparer.Singleton.Equals(schema, mergedElem) == true);
                    dataMerger[mergedElem] = mergedElem;
                }
                else
                {
                    dataMerger.Add(schema, schema);
                }
            }
        }
Example #3
0
        public static IEnumerable <PgoSchemaElem> ParsePgoData <TType>(IPgoSchemaDataLoader <TType> dataProvider, IEnumerable <long> inputDataStream, bool longsAreCompressed)
        {
            int           dataCountToRead = 0;
            PgoSchemaElem curSchema       = default(PgoSchemaElem);
            InstrumentationDataProcessingState processingState = InstrumentationDataProcessingState.UpdateProcessMaskFlag;
            long lastDataValue = 0;
            long lastTypeValue = 0;

            foreach (long value in inputDataStream)
            {
                if (dataCountToRead > 0)
                {
                    if (curSchema.DataHeldInDataLong)
                    {
                        if (longsAreCompressed)
                        {
                            lastDataValue += value;
                        }
                        else
                        {
                            lastDataValue = value;
                        }
                        curSchema.DataLong = lastDataValue;
                    }
                    else
                    {
                        int dataIndex = curSchema.Count - dataCountToRead;
                        switch (curSchema.InstrumentationKind & PgoInstrumentationKind.MarshalMask)
                        {
                        case PgoInstrumentationKind.FourByte:
                            if (longsAreCompressed)
                            {
                                lastDataValue += value;
                            }
                            else
                            {
                                lastDataValue = value;
                            }
                            ((int[])curSchema.DataObject)[dataIndex] = checked ((int)lastDataValue);
                            break;

                        case PgoInstrumentationKind.EightByte:
                            if (longsAreCompressed)
                            {
                                lastDataValue += value;
                            }
                            else
                            {
                                lastDataValue = value;
                            }
                            ((long[])curSchema.DataObject)[dataIndex] = lastDataValue;
                            break;

                        case PgoInstrumentationKind.TypeHandle:
                            if (longsAreCompressed)
                            {
                                lastTypeValue += value;
                            }
                            else
                            {
                                lastTypeValue = value;
                            }
                            ((TType[])curSchema.DataObject)[dataIndex] = dataProvider.TypeFromLong(lastTypeValue);
                            break;
                        }
                    }
                    dataCountToRead--;
                    if (dataCountToRead == 0)
                    {
                        yield return(curSchema);

                        curSchema.DataLong   = 0;
                        curSchema.DataObject = null;
                    }
                    continue;
                }

                if (processingState == InstrumentationDataProcessingState.UpdateProcessMaskFlag)
                {
                    processingState = (InstrumentationDataProcessingState)value;
                    continue;
                }

                if ((processingState & InstrumentationDataProcessingState.ILOffset) == InstrumentationDataProcessingState.ILOffset)
                {
                    if (longsAreCompressed)
                    {
                        curSchema.ILOffset = checked ((int)(value + (long)curSchema.ILOffset));
                    }
                    else
                    {
                        curSchema.ILOffset = checked ((int)value);
                    }

                    processingState = processingState & ~InstrumentationDataProcessingState.ILOffset;
                }
                else if ((processingState & InstrumentationDataProcessingState.Type) == InstrumentationDataProcessingState.Type)
                {
                    if (longsAreCompressed)
                    {
                        curSchema.InstrumentationKind = (PgoInstrumentationKind)(((int)(curSchema.InstrumentationKind)) + checked ((int)value));
                    }
                    else
                    {
                        curSchema.InstrumentationKind = (PgoInstrumentationKind)value;
                    }

                    processingState = processingState & ~InstrumentationDataProcessingState.Type;
                }
                else if ((processingState & InstrumentationDataProcessingState.Count) == InstrumentationDataProcessingState.Count)
                {
                    if (longsAreCompressed)
                    {
                        curSchema.Count = checked ((int)(value + (long)curSchema.Count));
                    }
                    else
                    {
                        curSchema.Count = checked ((int)value);
                    }
                    processingState = processingState & ~InstrumentationDataProcessingState.Count;
                }
                else if ((processingState & InstrumentationDataProcessingState.Other) == InstrumentationDataProcessingState.Other)
                {
                    if (longsAreCompressed)
                    {
                        curSchema.Other = checked ((int)(value + (long)curSchema.Other));
                    }
                    else
                    {
                        curSchema.Other = checked ((int)value);
                    }
                    processingState = processingState & ~InstrumentationDataProcessingState.Other;
                }

                if (processingState == InstrumentationDataProcessingState.Done)
                {
                    processingState = InstrumentationDataProcessingState.UpdateProcessMaskFlag;

                    if (curSchema.InstrumentationKind == PgoInstrumentationKind.Done)
                    {
                        yield break;
                    }

                    switch (curSchema.InstrumentationKind & PgoInstrumentationKind.MarshalMask)
                    {
                    case PgoInstrumentationKind.None:
                        yield return(curSchema);

                        break;

                    case PgoInstrumentationKind.FourByte:
                        if (curSchema.Count > 1)
                        {
                            curSchema.DataObject = new int[curSchema.Count];
                        }
                        dataCountToRead = curSchema.Count;
                        break;

                    case PgoInstrumentationKind.EightByte:
                        if (curSchema.Count > 1)
                        {
                            curSchema.DataObject = new long[curSchema.Count];
                        }
                        dataCountToRead = curSchema.Count;
                        break;

                    case PgoInstrumentationKind.TypeHandle:
                        curSchema.DataObject = new TType[curSchema.Count];
                        dataCountToRead      = curSchema.Count;
                        break;

                    default:
                        throw new Exception("Unknown Type");
                    }
                }
            }

            throw new Exception("Partial Instrumentation Data");
        }