2011-06-24 17 views
1

我要寻找高性能的Java库,它提供了一些方法,可以让我得到:任何使用时间戳的优秀高性能java库?

  1. 当前的小时(0-24)
  2. 当天(1-31)
  3. 本周(1 52)
  4. 本月(1-12)
  5. 当前季节(1-4)
  6. 本年度(YYYY或YY)

性能对我来说是最重要的问题。这就是为什么我不能使用标准的Calendar类。最好的解决方案是在不创建新对象的情况下进行所有计算。

增加:为了澄清我会再提一次:更多的是每秒100000次操作。

+0

这有什么错日历? – adarshr

+0

日历非常慢。我需要做约+100000操作。日历不适合我的情况。需要一些纯数学的公式。没有物体。 – Worker

+0

+ 100000在多少时间?如果你必须在1天内这样做,没问题:-) – Riduidel

回答

3

你实际上可以使用excellant joda时间库来做到这一点。 joda中的Chronology实现提供了DateTime getHourgetDay类型方法背后的逻辑。如果您希望跳过创建DateTime时刻,直接使用它没有问题。

long msSinceEpoch = System.currentTimeMillis(); 

Chronology chronology = ISOChronology.getInstanceUTC() // This can be static 

chronology.hourOfDay().get(msSinceEpoch); 
chronology.dayOfMonth().get(msSinceEpoch); 
chronology.weekOfWeek().get(msSinceEpoch); 
chronology.monthOfYear().get(msSinceEpoch); 
chronology.years().get(msSinceEpoch); 

会话不是joda有概念的东西。根据你自己的规则,你必须从月份开始。

joda-time documentation on Chronology

+0

对,季节我可以轻松计算自己:-)谢谢你的建议! – Worker

+0

嗨戴维斯,JODA的工作就像一个魅力。每秒400万次操作。只是想知道您使用的是哪个JDK?很奇怪你有System.currentTimeInMillis();我只有System.currentTimeMillis();再次感谢你和英格兰的一切! – Worker

+1

我使用我自己定制的OpenJDK版本,我自己编译并在智能手机上运行,​​只是为了骚扰Oracle –

3

你确定Calendar太慢还是你相信它?你有没有尺寸呢?在Java中创建新对象相当便宜。保持它们很昂贵。

也就是说,要么尝试Joda Time,要么将Java代码中的算法复制到静态辅助方法中。

+0

非常感谢你的建议亚伦。当然,我做了一些测量。日历非常慢,它的实现不能处理我的负载。 – Worker

+1

我尝试[测量它](http://stackoverflow.com/questions/6465330/any-good-high-performance-java-library-that-works-with-timestamp/6467860#6467860)与建议的使用问题和接受答案。在这种情况下,日历似乎比乔达跑得快。 – sudocode

1

仅使用一个对象,并更新它的时候,像这样:

Date d = new Date(); 
... 
d.setTime(System.currentTimeMillis()); 
+0

Sun的java.util.Date版本在调用setTime()之后创建一个新对象,所以我猜它不适合。 – fernacolo

+0

@fernacolo的任何来源?我没有意识到这一点。 – Giann

+1

我无法粘贴Sun的代码,因为它的版权和“机密”,但您可以检查以下操作:安装JDK 5或更早版本,打开src.zip,查找java/util/Date.java,并查看setTime(long millis )。这将清除称为cdate的引用。然后,无论何时您需要某个组件(如year,day),它都会调用normalize()来为该引用实例化一个新对象。 – fernacolo

1

您可以使用Joda Time因为它比日历快得多,而做到这一点:

LocalDateTime now = new LocalDateTime(); // automatically points to current datetime. 
int hour = now.getHourOfDay(); 
int day = now.getDayOfMonth(); 
int week = now.getWeekOfWeekyear(); 
int month = now.getMonthOfYear(); 
int year = now.getYear(); 
int season = getSeason(day, month); 

的getSeason()很容易实现。没有任何解决方案可以在不创建任何对象的情况下完成这一切。顺便说一句,为什么你需要这么多的表演?!?!

2

您可以获取当前时间,并通过除法和余数计算当前小时数,分钟数,秒数,毫秒数。日,月,年只是每天更换一次,所以您只需在计算时间内进行计算。

可以使用缓存的日/月/年计算,其余的亚微秒的时间,而无需创建对象(超过每天一次)

import java.util.Calendar; 
import java.util.TimeZone; 

public class Daytime { 
    private static final long HOUR_MS = 3600*1000; 

    public short year; 
    public byte month, day; 
    public byte hour, min, sec; 
    public short millis; 

    private long lastMillis = Integer.MIN_VALUE; 
    private final TimeZone timeZone; 
    private long timeOffset; 

    public Daytime() { 
     timeZone = TimeZone.getTimeZone("UTC"); 
     now(); 
    } 

    public Daytime(TimeZone timeZone) { 
     this.timeZone = timeZone; 
     now(); 
    } 

    public void now() { 
     long now = System.currentTimeMillis() + timeOffset; 
     if (now == lastMillis) return; 
     long cachePeriod = now/HOUR_MS; 
     // could the day have changed? 
     if (cachePeriod != lastMillis/HOUR_MS) { 
      timeOffset = timeZone.getOffset(now); 
      Calendar cal = Calendar.getInstance(timeZone); 
      year = (short) cal.get(Calendar.YEAR); 
      month = (byte) cal.get(Calendar.MONTH); 
      day = (byte) cal.get(Calendar.DAY_OF_MONTH); 
      hour = (byte) cal.get(Calendar.HOUR); 
     } 
     millis = (short) (now % 1000); 
     now /= 1000; 
     sec = (byte) (now % 60); 
     now /= 60; 
     min = (byte) (now % 60); 
    } 

    public static void main(String... args) { 
     Daytime dt = new Daytime(); 
     long start = System.nanoTime(); 
     final int runs = 10 * 1000 * 1000; 
     for(int i=0;i< runs;i++) 
      dt.now(); 
     long time = System.nanoTime() - start; 
     System.out.printf("Daytime.now() took %.3f micro-seconds on average%n", time/1e3/runs); 
    } 
} 

打印

Daytime.now() took 0.287 micro-seconds on average 

关于夏令时变化的发生有多种假设。您可能需要更改检查周期以适应您的需要。

+0

感谢您提供基准代码。实际上,我必须为大量的在线和离线用户计算一些接近实时的统计数据。这个数据基于我在上面提到的问题中提到的数字。这就是为什么我很难调整计算。 – Worker

+0

我相信使用缓存信息是最好的选择。如果你想要亚毫秒时间,你需要使用System.nanoTime()或通过JNI进行系统调用。 –

1

注意Calendar.getInstance是相当昂贵的,但你可以通过调用该方法一次,并重新使用(除非你需要每个线程的日历:日历不是线程安全的),通常得到您的日历对象。

+0

我跑了一个小板凳,可以在1秒内调用Calendar.getInstance()50.000次。这是如何慢? – Dorus

+0

_我可以在1秒内创建500万个不同的字符串循环。为什么我应该关心在执行热点中创建大量字符串?_如果您查看日历创建,它不完全是轻量级操作。如果您在执行热点中分析代码,我认为您会发现,每次需要日历时,维护单个日历将比调用Calendar.getInstance便宜。我似乎记得自己在生产代码中做出这种改变。但这只是一个建议。 – sudocode

+0

顺便说一句,在你的基准测试中试试这个。在循环中使用calendar.getTime()获取日期。版本1:日历在循环内部创建。版本2:日历在循环之前创建。重复一遍。哪个跑得快? (我发现版本2运行速度快了20倍)。 – sudocode

1

我已经所以,现在,我终于下载了它,并给它一个尝试了解约达时间那么多帖子。

Gareth Davis的回答已经被接受,我对此没有任何问题。但我很想知道Joda Time在哪里做出了改变。

基于这个问题和接受的答案,我做了一个类来比较JDK Calendar和Joda Time Chronology的执行时间。

我发现日历实现的运行速度始终更快,速度并不快。

import java.util.Calendar; 
import java.util.Date; 

import org.joda.time.Chronology; 
import org.joda.time.chrono.ISOChronology; 


public class CalendarTest { 

    private static final int ITERATIONS = 1000000; 

    public static void main(String[] args) { 
     for (int i = 0; i < 10; i++) { 
      jdkCalendar(); 
      jodaChronology(); 
     } 
    } 

    private static void jdkCalendar() { 
     long start = System.currentTimeMillis(); 
     Calendar c = Calendar.getInstance(); 
     int hourOfDay = 0; 
     int dayOfMonth = 0; 
     int weekOfYear = 0; 
     int month = 0; 
     int year = 0; 
     for (int i = 0; i < ITERATIONS; i++) { 
      c.setTimeInMillis(System.currentTimeMillis()); 
      hourOfDay = c.get(Calendar.HOUR_OF_DAY); 
      dayOfMonth = c.get(Calendar.DAY_OF_MONTH); 
      weekOfYear = c.get(Calendar.WEEK_OF_YEAR); 
      month = c.get(Calendar.MONTH); 
      year = c.get(Calendar.YEAR); 
     } 
     long duration = System.currentTimeMillis() - start; 
     System.err.printf("jdk: duration %d, hourOfDay: %d, dayOfMonth: %d, weekOfYear: %d, month: %d, year: %d\n", duration, hourOfDay, dayOfMonth, weekOfYear, month, year); 
    } 

    private static void jodaChronology() { 
     long start = System.currentTimeMillis(); 
     Chronology chronology = ISOChronology.getInstanceUTC(); // This can be static 
     int hourOfDay = 0; 
     int dayOfMonth = 0; 
     int weekOfYear = 0; 
     int month = 0; 
     int year = 0; 
     for (int i = 0; i < ITERATIONS; i++) { 
      long msSinceEpoch = System.currentTimeMillis(); 
      hourOfDay = chronology.hourOfDay().get(msSinceEpoch); 
      dayOfMonth = chronology.dayOfMonth().get(msSinceEpoch); 
      weekOfYear = chronology.weekOfWeekyear().get(msSinceEpoch); 
      month = chronology.monthOfYear().get(msSinceEpoch); 
      year = chronology.years().getValue(msSinceEpoch); 
     } 
     long duration = System.currentTimeMillis() - start; 
     System.err.printf("joda: duration %d, hourOfDay: %d, dayOfMonth: %d, weekOfYear: %d, month: %d, year: %d\n", duration, hourOfDay, dayOfMonth, weekOfYear, month, year); 
    } 

} 

输出示例:

jdk: duration 1714, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 2099, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 377, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 689, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 340, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 680, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 330, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 653, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 326, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 596, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 337, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 620, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 471, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 590, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 326, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 591, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 336, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 595, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
jdk: duration 327, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 5, year: 2011 
joda: duration 560, hourOfDay: 12, dayOfMonth: 24, weekOfYear: 25, month: 6, year: 41 
+0

嗨Sudocode!非常感谢您的基准。我也是这样做的(代码有点不同,但也有1 000 000个操作)。我有JODA:约300和日历〜720。没有那么多,但仍然对我来说日历更慢。我测试了Java版本“1.6.0_22” Java™SE运行时环境(版本1.6.0_22-b04-307-10M3261) Java HotSpot™64位服务器VM(版本17.1-b03-307,混合模式) – Worker

+0

@MinimeDJ我现在试着用3个不同的JVM运行相同的代码,第一个是我最初的基准测试:** IBM Corporation,1.5.0 **,2.3,IBM J9 VM。 ** Sun Microsystems Inc.,1.6.0_24 **,19.1-b02,Java HotSpot™64位服务器虚拟机。 ** IBM公司,1.6.0 **,2.4,IBM J9 VM。 1.6 JVM的性能总体上更好,但JDK与Joda没有反转。对于此代码,JDK日历实现仍然一直优于Joda Chronlogy实现。 – sudocode

+0

确实很奇怪 – Worker