gpt4 book ai didi

java - java中从值获取枚举常量的优化方法

转载 作者:行者123 更新时间:2023-12-01 22:32:30 24 4
gpt4 key购买 nike

我需要具有字节值的枚举常量,可以在 super 性能排序系统中使用。然而,当我需要从相应的字节值获取枚举时,这会出现问题。 IE fromValue()。

我想知道当我想要高度优化的东西时,使用 Byte 值到常量的映射的以下方法是否被认为是一个坏主意,或者我是否应该坚持使用静态常量。我试图避免的是在运行时循环遍历枚举值以找到正确的值,我相信这会在执行数百万次此类操作时增加不必要的开销。

public enum ReferenceTargetType {
BINARY((byte)0x1),
TOPIC((byte)0x2),
MAP((byte)0x3),
UNKNOWN((byte)0x4);

private static Map<Byte,ReferenceTargetType> targetTypeMap = new HashMap<Byte,ReferenceTargetType>();

static {
for(ReferenceTargetType type : ReferenceTargetType.values()){
targetTypeMap.put(type.getValue(), type);
}
}

private byte value;

ReferenceTargetType(byte value){
this.value = value;
}

byte getValue(){
return this.value;
}

static ReferenceTargetType fromValue(byte value){
return targetTypeMap.get(value);
}
}

谢谢

更新

我创建了一些测试来查看各种方法的性能。第一个方法使用 hashmap,第二个方法通过循环值、第三个数组偏移量和第四个数组偏移量使用 int 而不是字节(为了查看从 byte 到 int 的向上转换是否会对性能产生影响),第五种方法使用 switch 。

平均运行次数超过 100 次,每次运行执行 1 亿次 fromValue() 调用。时间以毫秒为单位(我将其从纳米时间更改为更大的值,因为它对我来说是爆炸性的)。

结果如下:

  • 运行 1 次平均值:385(HashMap 查找)
  • 运行 2 平均值:914(循环值)
  • 运行 3 次平均值:0(数组(字节))
  • 运行 4 次平均值:0(数组(int))
  • 运行 5 次平均值:314(切换)

和代码:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.HashMap;
import java.util.Map;

@RunWith(JUnit4.class)
public class EnumFromValueTest {

static int masterRuns = 100;
static int runs = 100000000;
static long[] r1runs = new long[masterRuns];
static long[] r2runs = new long[masterRuns];
static long[] r3runs = new long[masterRuns];
static long[] r4runs = new long[masterRuns];
static long[] r5runs = new long[masterRuns];

static long average(long[] values){

int total = 0;
for(int i = 0; i < values.length; i++)
{
total += values[i];
}
int average = total / values.length;

return average;

}

public enum ReferenceTargetType1 {
BINARY((byte)0x0),
TOPIC((byte)0x1),
MAP((byte)0x2),
UNKNOWN((byte)0x3);

private static
Map<Byte,ReferenceTargetType1>
targetTypeMap = new HashMap<Byte, ReferenceTargetType1>();

static {
for(ReferenceTargetType1 type : ReferenceTargetType1.values()){
targetTypeMap.put(type.getValue(), type);
}
}

private byte value;

ReferenceTargetType1(byte value){
this.value = value;
}

byte getValue(){
return this.value;
}

static ReferenceTargetType1 fromValue(byte value){

return targetTypeMap.get(value);
}

}

public enum ReferenceTargetType2 {
BINARY((byte)0x0),
TOPIC((byte)0x1),
MAP((byte)0x2),
UNKNOWN((byte)0x3);

private byte value;

ReferenceTargetType2(byte value){
this.value = value;
}

byte getValue(){
return this.value;
}

static ReferenceTargetType2 fromValue(byte value){
for(ReferenceTargetType2 type : ReferenceTargetType2.values()){
if(type.getValue() == value)
return type;
}

return null;
}

}

public enum ReferenceTargetType3 {
BINARY((byte)0x0),
TOPIC((byte)0x1),
MAP((byte)0x2),
UNKNOWN((byte)0x3);

private byte value;

private static ReferenceTargetType3[] values = new ReferenceTargetType3[ReferenceTargetType3.values().length];
static {
int i = 0;
for(ReferenceTargetType3 type : ReferenceTargetType3.values()){
values[i]= type;
i++;
}
}
ReferenceTargetType3(byte value){
this.value = value;
}

byte getValue(){
return this.value;
}

static ReferenceTargetType3 fromValue(byte value){
return values[value];
}

}




public enum ReferenceTargetType4 {
BINARY(0),
TOPIC(1),
MAP(2),
UNKNOWN(3);

private int value;

private static ReferenceTargetType4[] values = new ReferenceTargetType4[ReferenceTargetType4.values().length];
static {

int i = 0;
for(ReferenceTargetType4 type : ReferenceTargetType4.values()){
values[i]= type;
i++;
}

}
ReferenceTargetType4(int value){
this.value = value;
}

int getValue(){
return this.value;
}

static ReferenceTargetType4 fromValue(int value){
return values[value];
}

}

public enum ReferenceTargetType5 {
BINARY((byte)0x0),
TOPIC((byte)0x1),
MAP((byte)0x2),
UNKNOWN((byte)0x3);

private byte value;

ReferenceTargetType5(byte value){
this.value = value;
}

byte getValue(){
return this.value;
}

static ReferenceTargetType5 fromValue(byte value) {
switch (value) {
case 0x0: return BINARY;
case 0x1: return TOPIC;
case 0x2: return BINARY;
case 0x3: return UNKNOWN;
default: return UNKNOWN;
}
}

}

@Test
public void doPerformanceTest(){

for(int i = 0; i < masterRuns;i++){
doRuns(i);
}

System.out.println("Run 1 average: " + average(r1runs));
System.out.println("Run 2 average: " + average(r2runs));
System.out.println("Run 3 average: " + average(r3runs));
System.out.println("Run 4 average: " + average(r4runs));
System.out.println("Run 5 average: " + average(r5runs));
}

public void doRuns(int runnum){

ReferenceTargetType1 type1 = ReferenceTargetType1.UNKNOWN;
ReferenceTargetType2 type2 = ReferenceTargetType2.UNKNOWN;
ReferenceTargetType3 type3 = ReferenceTargetType3.UNKNOWN;
ReferenceTargetType4 type4 = ReferenceTargetType4.UNKNOWN;
ReferenceTargetType5 type5 = ReferenceTargetType5.UNKNOWN;

long startTime1 = System.currentTimeMillis();

for(int i = 0; i < runs;i++){
ReferenceTargetType1.fromValue(type1.getValue());
}
r1runs[runnum] = (System.currentTimeMillis() - startTime1);

long startTime2 = System.currentTimeMillis();

for(int i = 0; i < runs;i++){
ReferenceTargetType2.fromValue(type2.getValue());
}
r2runs[runnum] = (System.currentTimeMillis() - startTime2);

long startTime3 = System.currentTimeMillis();

for(int i = 0; i < runs;i++){
ReferenceTargetType3.fromValue(type3.getValue());
}

r3runs[runnum] = (System.currentTimeMillis() - startTime3);

long startTime4 = System.currentTimeMillis();

for(int i = 0; i < runs;i++){
ReferenceTargetType4.fromValue(type4.getValue());
}

r4runs[runnum] = (System.currentTimeMillis() - startTime4);

long startTime5 = System.currentTimeMillis();

for(int i = 0; i < runs;i++){
ReferenceTargetType5.fromValue(type5.getValue());
}

r5runs[runnum] = (System.currentTimeMillis() - startTime5);


}
}

最佳答案

显然,数组是最快的解决方案。类似的东西

private final static ReferenceTargetType TYPES = ReferenceTargetType.values();

public ReferenceTargetType byteToType(byte b) {
int index = b - 1;
if (0<=index && index<TYPES.length) return TYPES[index];
... throw SomeException or return null;
}

任何东西都无法击败,除了硬编码的 switchif(尽管我强烈怀疑)。

由于这很可能比其他操作快得多(您必须以某种方式获取字节并且结果以某种方式被使用),所以我会在这里停下来。无需再优化。

<小时/>

如果您的字节值不同,您需要以不同的方式初始化数组,并可能使其更长,但除此之外没有任何变化。

<小时/>

使用 JNI 进行像数组访问这样简单的操作,其效率就像乘坐飞机去洗手间一样高效。它很复杂,开销很大,但也许也是一个很酷的因素。

关于java - java中从值获取枚举常量的优化方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27436619/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com