我要寻找高性能的Java库,它提供了一些方法,可以让我得到:任何使用时间戳的优秀高性能java库?
- 当前的小时(0-24)
- 当天(1-31)
- 本周(1 52)
- 本月(1-12)
- 当前季节(1-4)
- 本年度(YYYY或YY)
性能对我来说是最重要的问题。这就是为什么我不能使用标准的Calendar类。最好的解决方案是在不创建新对象的情况下进行所有计算。
增加:为了澄清我会再提一次:更多的是每秒100000次操作。
我要寻找高性能的Java库,它提供了一些方法,可以让我得到:任何使用时间戳的优秀高性能java库?
性能对我来说是最重要的问题。这就是为什么我不能使用标准的Calendar类。最好的解决方案是在不创建新对象的情况下进行所有计算。
增加:为了澄清我会再提一次:更多的是每秒100000次操作。
你实际上可以使用excellant joda时间库来做到这一点。 joda中的Chronology
实现提供了DateTime getHour
getDay
类型方法背后的逻辑。如果您希望跳过创建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有概念的东西。根据你自己的规则,你必须从月份开始。
你确定Calendar
太慢还是你相信它?你有没有尺寸呢?在Java中创建新对象相当便宜。保持它们很昂贵。
也就是说,要么尝试Joda Time,要么将Java代码中的算法复制到静态辅助方法中。
仅使用一个对象,并更新它的时候,像这样:
Date d = new Date();
...
d.setTime(System.currentTimeMillis());
您可以使用java.util.Calander,如果不满意,你可以使用可能Joda Time。
这可以帮助你。
您可以使用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()很容易实现。没有任何解决方案可以在不创建任何对象的情况下完成这一切。顺便说一句,为什么你需要这么多的表演?!?!
您可以获取当前时间,并通过除法和余数计算当前小时数,分钟数,秒数,毫秒数。日,月,年只是每天更换一次,所以您只需在计算时间内进行计算。
可以使用缓存的日/月/年计算,其余的亚微秒的时间,而无需创建对象(超过每天一次)
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
关于夏令时变化的发生有多种假设。您可能需要更改检查周期以适应您的需要。
感谢您提供基准代码。实际上,我必须为大量的在线和离线用户计算一些接近实时的统计数据。这个数据基于我在上面提到的问题中提到的数字。这就是为什么我很难调整计算。 – Worker
我相信使用缓存信息是最好的选择。如果你想要亚毫秒时间,你需要使用System.nanoTime()或通过JNI进行系统调用。 –
注意Calendar.getInstance是相当昂贵的,但你可以通过调用该方法一次,并重新使用(除非你需要每个线程的日历:日历不是线程安全的),通常得到您的日历对象。
我跑了一个小板凳,可以在1秒内调用Calendar.getInstance()50.000次。这是如何慢? – Dorus
_我可以在1秒内创建500万个不同的字符串循环。为什么我应该关心在执行热点中创建大量字符串?_如果您查看日历创建,它不完全是轻量级操作。如果您在执行热点中分析代码,我认为您会发现,每次需要日历时,维护单个日历将比调用Calendar.getInstance便宜。我似乎记得自己在生产代码中做出这种改变。但这只是一个建议。 – sudocode
顺便说一句,在你的基准测试中试试这个。在循环中使用calendar.getTime()获取日期。版本1:日历在循环内部创建。版本2:日历在循环之前创建。重复一遍。哪个跑得快? (我发现版本2运行速度快了20倍)。 – sudocode
我已经所以,现在,我终于下载了它,并给它一个尝试了解约达时间那么多帖子。
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
嗨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
@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
确实很奇怪 – Worker
这有什么错日历? – adarshr
日历非常慢。我需要做约+100000操作。日历不适合我的情况。需要一些纯数学的公式。没有物体。 – Worker
+ 100000在多少时间?如果你必须在1天内这样做,没问题:-) – Riduidel