Algorithm 以微秒的精度压缩unix时间戳

Algorithm 以微秒的精度压缩unix时间戳,algorithm,optimization,encoding,compression,Algorithm,Optimization,Encoding,Compression,我有一个文件,它由一系列实时unix时间戳组成,精确到微秒,即时间戳永远不会减少。所有需要编码/解码的时间戳都来自同一天。文件中的示例条目可能类似于1364281200.078739,对应于1364281200078739 usecs。数据的间隔和边界不均匀 我需要实现大约10位/时间戳的压缩。目前,通过计算连续时间戳之间的差异,我能够将平均值压缩到31位/时间戳。如何进一步改进 编辑: 我们将压缩程度计算为(以字节为单位的编码文件大小)/(时间戳数)*8。我将时间戳分为“.”之前和之后的两部分

我有一个文件,它由一系列实时unix时间戳组成,精确到微秒,即时间戳永远不会减少。所有需要编码/解码的时间戳都来自同一天。文件中的示例条目可能类似于1364281200.078739,对应于1364281200078739 usecs。数据的间隔和边界不均匀

我需要实现大约10位/时间戳的压缩。目前,通过计算连续时间戳之间的差异,我能够将平均值压缩到31位/时间戳。如何进一步改进

编辑:


我们将压缩程度计算为(以字节为单位的编码文件大小)/(时间戳数)*8。我将时间戳分为“.”之前和之后的两部分。整数部分是非常恒定的,两个整数部分时间戳之间的最大差值是32,所以我使用0-8位对其进行编码。精度部分非常随机,因此我忽略了前导位,并使用0-21位写入文件(最大值为999999)。但我的编码文件的大小是4007674字节,因此压缩为71.05比特/秒。我还写入“.”和两个时间戳之间的空格,以便稍后解码。如何改进编码文件的大小

下面是部分数据集的链接-

以下是以微秒为单位的差分时间戳值的链接-
b/w时间戳的最大差异为-32594136微秒。

如果看不到数据差异的直方图,很难知道。我会尝试对差异进行编码,选择参数以获得差异分布的最佳压缩。

如果需要微秒精度的无损压缩,请注意10位将允许您计数到1024

如果事件的计时是随机的,并且您实际上需要指定的微秒精度,这意味着您的差分时间戳的方差不能超过约1毫秒,而不超过您的10位/事件预算

基于对数据的快速浏览,您可能无法获得10位/时间戳。然而,差分是正确的第一步,可以做得比31位更好——我会对样本数据集进行统计,并选择反映该分布的二进制前缀编码


你应该确保你的代码有必要对大的空隙进行编码,所以请考虑在.

基础上,如果你把每个时间戳和上一个时间戳之间的间隔用微秒表示(即整数),那么你的样本文件中每比特深度的值的分布是:

因此,52.285%的值是0或1,64位以下(2~6位)只有少数其他值,27.59%的值是7~12位,大约2.1%的分布相当均匀,最多20位,20位以上只有3%,最多25位。 看看这些数据,也很明显,有许多序列最多有6个连续的零

这些观察结果让我想到了使用每个值的可变位大小,如下所示:

00 0xxxxx 0 (xxxxx is the number of consecutive zeros) 00 1xxxxx 1 (xxxxx is the number of consecutive ones) 01 xxxxxx xxxxxxxx 2-14 bit values 10 xxxxxx xxxxxxxx xxxxxxxx 15-22 bit values 11 xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 23-30 bit values 序列表:

index ~ seq index ~ seq index ~ seq index ~ seq index ~ seq index ~ seq 0 0 2 00 6 000 14 0000 30 00000 62 000000 1 1 3 01 7 001 15 0001 31 00001 63 000001 4 10 8 010 16 0010 32 00010 5 11 ... ... ... 11 101 27 1101 59 11101 12 110 28 1110 60 11110 13 111 29 1111 61 11111 索引~序号索引~序号索引~序号索引~序号索引~序号索引~序号索引~序号索引 0 0 2 00 6 000 14 0000 30 00000 62 000000 1 1 3 01 7 001 15 0001 31 00001 63 000001 4 10 8 010 16 0010 32 00010 5 11 ... ... ... 11 101 27 1101 59 11101 12 110 28 1110 60 11110 13 111 29 1111 61 11111 对于时间戳为451210的示例文件,这会将编码文件大小降低到676418字节,即每个时间戳11.99位

对上述方法的测试表明,在较大的间隔之间有98578个单零和31271个单零。因此,我尝试使用每个较大间隔的1位来存储它后面是否跟一个零,这将编码大小减少到592315字节。当我使用2位来存储较大的间隔后是0、1还是00(最常见的序列)时,编码大小减少到564034字节,或每个时间戳10.0004位。
然后,我改为使用以下大间隔存储单个0和1,而不是前一个(纯粹是为了代码简单),并发现这导致文件大小为563.884字节,或每个时间戳9.997722位

因此,完整的方法是:

Store the first timestamp (8 bytes), then store the intervals as either: 00 iiiiii sequences of up to 5 (or 6) zeros or ones 01 XXxxxx xxxxxxxx 2-12 bit values (2 ~ 4,095) 10 XXxxxx xxxxxxxx xxxxxxxx 13-20 bit values (4,096 ~ 1,048,575) 11 XXxxxx xxxxxxxx xxxxxxxx xxxxxxxx 21-28 bit values (1,048,576 ~ 268,435,455) iiiiii = index in sequence table (see above) XX = preceded by a zero (if XX=1), a one (if XX=2) or two zeros (if XX=3) xxx... = 12, 20 or 28 bit value 存储第一个时间戳(8字节),然后将间隔存储为: 00 IIII最多5(或6)个零或1的序列 01 XXxxxx xxxxxxxx 2-12位值(2~4095) 10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 13-20位值(4096~1048575) 11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 21-28位值(1048576~268435455) IIII=序列表中的索引(见上文) XX=前面有零(如果XX=1)、一(如果XX=2)或两个零(如果XX=3) xxx…=12、20或28位值 编码器的示例:

#包括
#包括
#包括
使用名称空间std;
void write_timestamp(流和文件的,uint64_t timestamp){//big-endian
uint8_t字节[8];
对于(inti=7;i>=0;i--,时间戳>>=8)字节[i]=时间戳;
写入((char*)字节,8);
}
int main(){
ifstream ifile(“timestamps.txt”);
如果(!ifile.is_open())返回1;
文件流(“output.bin”,ios::trunc | ios::binary);
如果(!ofile.is_open())返回2;
长双秒;
uint64_t时间戳;
如果(i文件>>秒){
时间戳=秒*1000000;
写入时间戳(ofile,时间戳);
}
而(!ifile.eof()){
uint8_t bytesize=0,len=0,seq=0,字节[4];
Store the first timestamp (8 bytes), then store the intervals as either: 

00 iiiiii                             sequences of up to 5 (or 6) zeros or ones
01 XXxxxx xxxxxxxx                     2-12 bit values (2 ~ 4,095)
10 XXxxxx xxxxxxxx xxxxxxxx           13-20 bit values (4,096 ~ 1,048,575)
11 XXxxxx xxxxxxxx xxxxxxxx xxxxxxxx  21-28 bit values (1,048,576 ~ 268,435,455)

iiiiii = index in sequence table (see above)
XX     = preceded by a zero (if XX=1), a one (if XX=2) or two zeros (if XX=3)
xxx... = 12, 20 or 28 bit value