Cha*_*win 9 java performance flags memory-management bit-manipulation
使用整数标志和按位运算是减少高容量对象的内存占用的有效方法吗?
记忆足迹
我的理解是,通常将a boolean存储为intJVM实现中的一个.它是否正确?在这种情况下,32个标志肯定代表了大量的内存占用减少.
虽然JVM实现当然有所不同,但情况可能并非总是如此.
性能
我的理解是,CPU是非常数字驱动的,并且按位操作与计算中的内容一样高效.
在布尔运算中使用按位运算会有性能损失 - 甚至是增益吗?
备择方案
有没有更好的方法来完成同样的事情?Enum是否允许组合标志,即FLAGX = FLAG1 | FLAG2?
注意,最后一个方法propogateMove()是递归的,可能每秒被调用数百次,并且直接影响我们应用程序的响应性,因此使用标志来避免逻辑位并调用其他方法.
// FLAGS helper functions
private final void setclear(int mask, boolean set) { if (set) set(mask); else clear(mask); }
private final void set(int mask) { flags |= mask; }
private final void clear(int mask) { flags &= ~mask; }
private final boolean test(int mask) { return ((flags & mask) == mask); }
// Flags //////////////////////////////////////////////////////////////////////
private static final boolean HORIZONTAL = true;
private static final boolean VERTICAL = false;
private static final int ORIENT = 0x00000001;
private static final int DISPLAY = 0x00000002;
private static final int HSHRINK = 0x00000004;
private static final int VSHRINK = 0x00000008;
private static final int SHRINK = HSHRINK | VSHRINK;
private static final int TILE_IMAGE = 0x00000010;
private static final int CURSOR = 0x00000020;
private static final int MOUSEINSIDE = 0x00000040;
private static final int MOUSEINSIDE_BLOCKED = 0x00000080;
private static final int CONSTRAIN = 0x00000100;
private static final int CONSTRAIN_DESCENDENT = 0x00000200;
private static final int PLACE = 0x00000400;
private static final int PLACE_DESCENDENT = 0x00000800;
private static final int REFLOW = CONSTRAIN | CONSTRAIN_DESCENDENT | PLACE | PLACE_DESCENDENT;
private static final int PACK = 0x00001000;
private static final int CLIP = 0x00002000;
private static final int HAS_WIDTH_SLACK = 0x00004000;
private static final int HAS_HEIGHT_SLACK = 0x00008000;
private static final int ALIGN_TOP = 0x00010000;
private static final int ALIGN_BOTTOM = 0x00020000;
private static final int ALIGN_LEFT = 0x00040000;
private static final int ALIGN_RIGHT = 0x00080000;
private static final int ALIGNS = ALIGN_TOP | ALIGN_BOTTOM | ALIGN_LEFT | ALIGN_RIGHT;
private static final int ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT;
private static final int ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT;
private static final int ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT;
private static final int ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT;
private static final int ENTER_TRAP = 0x00100000;
private static final int LEAVE_TRAP = 0x00200000;
private static final int _MOVE_TRAP = 0x00400000;
private static final int MOVE_TRAP = 0x00800000;
private static final int CHILDREN_READ_TRAP = 0x01000000;
private static final int CHILDREN_TRAP = 0x02000000;
private static final int PLACE_CLEAN = 0x03000000;
private static final int SHRINK_TRAP = 0x04000000;
private static final int HSHRINK_TRAP = 0x10000000;
private static final int VSHRINK_TRAP = 0x20000000;
//private static final int UNUSED = 0x40000000;
//private static final int UNUSED = 0x80000000;
// Flags in switch ////////////////////////////////////////////////////////////
/** get align value as a string from align flags */
private JS alignToJS() {
switch(flags & ALIGNS) {
case (ALIGN_TOPLEFT):
return SC_align_topleft;
case (ALIGN_BOTTOMLEFT):
return SC_align_bottomleft;
case (ALIGN_TOPRIGHT):
return SC_align_topright;
case (ALIGN_BOTTOMRIGHT):
return SC_align_bottomright;
case ALIGN_TOP:
return SC_align_top;
case ALIGN_BOTTOM:
return SC_align_bottom;
case ALIGN_LEFT:
return SC_align_left;
case ALIGN_RIGHT:
return SC_align_right;
case 0: // CENTER
return SC_align_center;
default:
throw new Error("This should never happen; invalid alignment flags: " + (flags & ALIGNS));
}
}
// Flags in logic /////////////////////////////////////////////////////////////
private final boolean propagateMove(int mousex, int mousey) throws JSExn {
// start with pre-event _Move which preceeds Enter/Leave
if (test(_MOVE_TRAP)) {
if (Interpreter.CASCADE_PREVENTED == justTriggerTraps(SC__Move, JSU.T)) {
// _Move cascade prevention induces Leave
propagateLeave();
// propagate cascade prevention
return true;
}
}
// REMARK: anything from here on in is a partial interruption relative
// to this box so we can not call propagateLeave() directly upon it
int i;
boolean interrupted = false;
if (!test(PACK)) {
// absolute layout - allows for interruption by overlaying siblings
for (Box b = getChild(i=treeSize()-1); b != null; b = getChild(--i)) {
if (!b.test(DISPLAY)) {
continue;
}
if (interrupted) {
b.propagateLeave();
continue;
}
int b_mx = mousex-getXInParent(b);
int b_my = mousey-getYInParent(b);
if (b.inside(b_mx, b_my)) {
if (b.propagateMove(b_mx, b_my)) {
interrupted = true;
}
} else {
b.propagateLeave();
}
}
} else {
// packed layout - interrupted still applies, plus packedhit shortcut
boolean packedhit = false;
for (Box b = getChild(i=treeSize()-1); b != null; b = getChild(--i)) {
if (!b.test(DISPLAY)) {
continue;
}
if (packedhit) {
b.propagateLeave();
continue;
}
int b_mx = mousex-getXInParent(b);
int b_my = mousey-getYInParent(b);
if (b.inside(b_mx, b_my)) {
packedhit = true;
if (b.propagateMove(b_mx, b_my)) {
interrupted = true;
}
} else {
b.propagateLeave();
}
}
}
// child prevented cascade during _Move/Move which blocks
// Enter on this box - invoking Leave if necessary
if (interrupted) {
if (test(MOUSEINSIDE)) {
if (!test(MOUSEINSIDE_BLOCKED)) {
// mouse previously inside, now blocked so invoke Leave
set(MOUSEINSIDE_BLOCKED);
if (test(LEAVE_TRAP)) {
justTriggerTraps(SC_Leave, JSU.T);
}
}
} else {
// mouse not previously inside, Enter not yet triggered, so
// do not invoke Leave
set(MOUSEINSIDE);
set(MOUSEINSIDE_BLOCKED);
}
// propagate cascade prevention
return true;
}
// set cursor if applicable to this box
if (test(CURSOR)) {
Surface s = getSurface();
if (s!=null && !s.cursorset) {
s.cursor = JSU.toString(getAndTriggerTraps(SC_cursor));
s.cursorset = true;
}
}
// fire Enter traps
if (!test(MOUSEINSIDE)) {
set(MOUSEINSIDE);
if (test(ENTER_TRAP)) {
justTriggerTraps(SC_Enter, JSU.T);
}
}
// finish post-event Move which follows Enter/Leave
if (test(MOVE_TRAP)) {
if (Interpreter.CASCADE_PREVENTED == justTriggerTraps(SC_Move, JSU.T)) {
// propagate cascade prevention
return true;
}
}
// propagation uninterrupted
return false;
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*rdt 13
我的理解是,通常在JVM实现中将布尔值存储为int.它是否正确?
当然,这取决于JVM的实现,但对于主流CPU的实现可能也是如此.
在这种情况下,32个标志肯定代表了大量的内存占用减少.
如果你实际上在一个类中有32个标志,并且该类有大量实例,那么.如果你从来没有超过几百个实例,那就不值得担心了.
我的理解是,CPU是非常数字驱动的,并且按位操作与计算中的内容一样高效.
这是真的.
在布尔运算中使用按位运算会有性能损失 - 甚至是增益吗?
这还取决于内存使用情况.如果只使用少量对象进行非常密集的操作,按位操作可能会减慢速度.如果你有很多对象,由于更好的缓存行为,减少的内存可能会大大提高性能.
有没有更好的方法来完成同样的事情?Enum是否允许组合标志,即FLAGX = FLAG1 | FLAG2?
您可以(并且应该)使用a而不是自己进行按位操作BitSet.是的,如果你可以使用Enums和an,它会更加清晰EnumSet,但是如果你有许多枚举,每个枚举都有几个元素,由于多个EnumSet实例的开销,它可能不会产生所需的内存节省.