我编写了一些Java软件,经常从Redis中保存和检索尤达-时间 DateTime对象。我现在只是序列化和反序列化对象。该软件读取对象的频率大约是它所写的的50倍。我还没有描述过序列化/反序列化Joda-Time对象的情况,但是在计算上,这个软件在负载下进行了很好的扩展,我对它的性能很满意。
没有很好地扩展的是内存的使用。序列化的Joda-Time对象非常大,一个相当大的Redis实例只需3天左右的客户数据,我就需要将其清除到磁盘上的关系数据库中。第二个问题是Redis自己的备份机制似乎难以管理更大的数据集.
撇开把更多RAM用于这个问题的诱惑放在一边,到目前为止,我想到了以下几个想法:
在决定之前,我将尝试并分析这些内容,但我想知道是否有人能想出一种更有效的方法来减少持久化Joda对象的内存占用而不破坏计算库?
发布于 2014-10-26 08:43:18
ISO 8601
我对Redis…一无所知一般来说,序列化Joda-Time对象的最简单和最有效的方法是利用它们对日期时值的合理、明确、标准的ISO 8601字符串格式的内置支持。
对于分区日期时间值,标准提供了YYYY-MM-DDTHH:MM:SS.SSS±HH:SS格式,如2014-10-24T21:17:30+02:00或2014-10-24T19:17:30Z (Z For Zulu意味着与UTC的偏移量为00:00 )。
各种Joda-Time2.5类使用ISO 8601作为解析和生成日期时间值的字符串表示的默认值。
生成串
对于DateTime,只需显式或隐式地调用其toString方法即可。
String output = DateTime.now( DateTimeZone.forID( "America/Montreal" ) ).toString();通常最好在存储日期-时间值时使用UTC。Joda-Time让您轻松地适应UTC。
DateTime nowMontreal = DateTime.now( DateTimeZone.forID( "America/Montreal" ) );
DateTime nowUtc = nowMontreal.withZone( DateTimeZone.UTC );
String output = nowUtc.toString();另一个例子。
DateTime output = DateTime.now( DateTimeZone.UTC ).toString();解析字符串
解析也同样容易。唯一的问题是时区。如果省略时区,通常Joda-Time将分配JVM当前的默认时区。如果显式指定所需的时区,通常情况下会更好。
DateTime dateTimeMontreal = new DateTime( "2014-10-24T19:17:30Z", DateTimeZone.forID( "America/Montreal" ) );或者,UTC…
DateTime dateTimeUtc = new DateTime( "2014-10-24T19:17:30Z", DateTimeZone.UTC ) );java.time
另一种选择是在Java 8中内置的新java.time包。受Joda-Time的启发,java.time在许多方面都是相似的。但一个不同之处在于,java.time在默认情况下通过扩展ISO8601标准来生成字符串表示,以附加时区的名称。虽然标准格式具有与UTC的偏移量,但您可以松散实际的时区信息.(时区是一个偏移加上夏令节约时间的规则,以及现在、将来和过去的其他异常情况。)
另一方面,通常情况下,最好将日期时间存储在UTC.如果您真的关心数据输入时的时区,那么除了UTC调整后的值之外,通常最好单独存储这些信息。
在java.time中,Instant类表示UTC中时间线上的某个时刻。
Instant instant = Instant.parse( "2014-10-24T19:17:30Z" );
String outputInstant = instant.toString();2014-10-24T19:17:30 Z
若要调整到时区,请指定ZoneId以获得ZonedDateTime。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
String outputZdt = zdt.toString();2014-10-24T15:17:30-04:00美国/蒙特利尔
发布于 2014-10-26 09:21:06
尝试分析日期时间对象的分布。如果它们之间的距离相对较近,那么你可以做一些“魔法”:
1)您可以引入一个特殊的“起始日期”常量,然后将实际日期存储为与常量相移的天数--即整数值(64位arch上的~8字节)。w/o压缩)
2)你需要实际时间吗?如果不是,只需浪费时间;如果是,则可以将hours+minutes+seconds存储在一个int变量中(64位arch上的另一个~8字节)。w/o压缩)
3)分析结果--在单个int变量中,有可能同时适用日期(移位)和时间。
4)引入缓存机制,这将大大提高序列化/反序列化对象的性能。
发布于 2019-05-21 09:32:56
从时代开始就储存米利斯。这是一个单一的长值。如果您需要一个时区值,也可以将时区Id存储为字符串。序列化和解析字符串表示总是需要更多的资源,包括RAM、内部的大量数据处理、一些正则表达式、分配更多内存的拆分调用。
使用这个构造函数来恢复值:public BaseDateTime(long instant, DateTimeZone zone),它非常轻巧,因为它存储在每个DateTime实例的遮罩下:
public BaseDateTime(long instant, Chronology chronology) {
super();
iChronology = checkChronology(chronology);
iMillis = checkInstant(instant, iChronology);
adjustForMinMax();
}https://stackoverflow.com/questions/26547596
复制相似问题