Exemple #1
0
        private (ByteWriter, string error) encodePacked()
        {
            if (len == 0)
            {
                return(null, null);
            }
            // Encode all but the first value.  Fist value is written unencoded
            // using 8 bytes.
            ByteWriter b = new ByteWriter(1 + 8 * len);

            // 4 high bits of first byte store the encoding type for the block
            b.Write((byte)(intCompressedSimple << 4));
            // Write the first value since it's not part of the encoded values
            b.Write(values[0]);
            var error = Simple8bEncoder.EncodeAll(values, 1, len, b);

            if (error != null)
            {
                b.Release();
                return(null, error);
            }
            return(b, null);
        }
Exemple #2
0
        public (ByteWriter, string) EncodingAll(Span <ulong> src)
        {
            int srclen = src.Length;

            if (srclen == 0)
            {
                return(null, null);  // Nothing to do
            }
            ulong max = 0, div = (ulong)1e12;

            ulong[] deltaarray = ArrayPool <ulong> .Shared.Rent(srclen);

            Span <ulong> deltas = new Span <ulong>(deltaarray);

            deltas[0] = src[0];
            ByteWriter result;

            if (srclen > 1)
            {
                for (int i = srclen - 1; i > 0; i--)
                {
                    deltas[i] = src[i] - src[i - 1];
                    if (deltas[i] > max)
                    {
                        max = deltas[i];
                    }
                }
                bool rle    = true;
                var  delta1 = deltas[1];
                for (int i = 2; i < srclen; i++)
                {
                    if (delta1 != deltas[i])
                    {
                        rle = false;
                        break;
                    }
                }
                // Deltas are the same - encode with RLE
                if (rle)
                {
                    // Large varints can take up to 10 bytes.  We're storing 3 + 1
                    // type byte.
                    result = new ByteWriter(31);
                    // 4 high bits used for the encoding type
                    result.Write((byte)(timeCompressedRLE << 4));
                    // The first value
                    result.Write(deltas[0]);
                    // The first delta, checking the divisor
                    // given all deltas are the same, we can do a single check for the divisor
                    ulong v = deltas[1];
                    while (div > 1 && v % div != 0)
                    {
                        div /= 10;
                    }
                    if (div > 1)
                    {
                        // 4 low bits are the log10 divisor
                        result.EndWrite()[0] |= (byte)Math.Log10(div);
                        result.Write(Varint.GetBytes(deltas[1] / div));
                    }
                    else
                    {
                        result.Write(Varint.GetBytes(deltas[1]));
                    }
                    // The number of times the delta is repeated
                    result.Write(Varint.GetBytes(srclen));
                    ArrayPool <ulong> .Shared.Return(deltaarray);

                    return(result, null);
                }
            }
            // We can't compress this time-range, the deltas exceed 1 << 60
            if (max > Simple8bEncoder.MaxValue)
            {
                // Encode uncompressed.
                int sz = 1 + srclen * 8;
                result = new ByteWriter(sz);
                result.Write((byte)(timeUncompressed << 4));
                for (int i = 0; i < srclen; i++)
                {
                    result.Write(deltas[i]);
                }
                ArrayPool <ulong> .Shared.Return(deltaarray);

                return(result, null);
            }
            // find divisor only if we're compressing with simple8b
            for (int i = 1; i < srclen && div > 1; i++)
            {
                // If our value is divisible by 10, break.  Otherwise, try the next smallest divisor.
                var v = deltaarray[i];
                while (div > 1 && v % div != 0)
                {
                    div /= 10;
                }
            }
            // Only apply the divisor if it's greater than 1 since division is expensive.
            if (div > 1)
            {
                for (int i = 1; i < srclen; i++)
                {
                    deltas[i] /= div;
                }
            }
            result = new ByteWriter(1 + srclen * 8);
            result.Write((byte)((timeCompressedPackedSimple << 4) | (byte)Math.Log10(div)));
            // Write the first value since it's not part of the encoded values
            result.Write(deltas[0]);
            // Encode with simple8b - fist value is written unencoded using 8 bytes.
            var error = Simple8bEncoder.EncodeAll(deltaarray, 1, srclen, result);

            if (error != null)
            {
                result.Release();
                return(null, error);
            }
            return(result, null);
        }
Exemple #3
0
 public TimeEncoder(int sz)
 {
     ts  = new ulong[Constants.DefaultMaxPointsPerBlock];
     enc = new Simple8bEncoder();
 }
Exemple #4
0
        public (ByteWriter, string) EncodingAll(Span <long> src)
        {
            int   srclen = src.Length;
            ulong max    = 0;

            ulong[] deltasarray = ArrayPool <ulong> .Shared.Rent(srclen);

            Span <ulong> deltas = new Span <ulong>(deltasarray);

            for (int i = srclen - 1; i > 0; i--)
            {
                long  l     = src[i] - src[i - 1];
                ulong delta = Encoding.ZigZagEncode(l);
                deltas[i] = delta;
                if (delta > max)
                {
                    max = delta;
                }
            }
            deltas[0] = Encoding.ZigZagEncode(src[0]);
            ByteWriter result;

            if (srclen > 2)
            {
                var rle = true;
                for (int i = 2; i < srclen; i++)
                {
                    if (deltas[1] != deltas[i])
                    {
                        rle = false;
                        break;
                    }
                }
                if (rle)
                {
                    // Large varints can take up to 10 bytes.  We're storing 3 + 1
                    // type byte.
                    result = new ByteWriter(31);
                    // 4 high bits used for the encoding type
                    result.Write((byte)(intCompressedRLE << 4));
                    // The first value
                    result.Write(deltas[0]);
                    // The first delta
                    result.Write(Varint.GetBytes(deltas[1]));
                    // The number of times the delta is repeated
                    result.Write(Varint.GetBytes(srclen - 1));
                    ArrayPool <ulong> .Shared.Return(deltasarray);

                    return(result, null);
                }
            }
            if (max > Simple8bEncoder.MaxValue)// There is an encoded value that's too big to simple8b encode.
            {
                // Encode uncompressed.
                int sz = 1 + srclen * 8;
                result = new ByteWriter(sz);
                result.Write((byte)(intUncompressed << 4));
                for (int i = 0; i < srclen; i++)
                {
                    result.Write(deltas[i]);
                }
                ArrayPool <ulong> .Shared.Return(deltasarray);

                return(result, null);
            }
            result = new ByteWriter(1 + srclen * 8);
            result.Write((byte)(intCompressedSimple << 4));
            // Write the first value since it's not part of the encoded values
            result.Write(deltas[0]);
            var error = Simple8bEncoder.EncodeAll(deltasarray, 1, srclen, result);

            ArrayPool <ulong> .Shared.Return(deltasarray);

            if (error != null)
            {
                result.Release();
                return(null, error);
            }
            return(result, null);
        }