Java integer tags and bitwise operations for memory reduction

Is the use of integer tags and bitwise operations an effective way to reduce the memory footprint of large objects?

>Memory footprint

My understanding is that in JVM implementations, a Boolean value is usually stored as an int. is it correct? In this case, 32 flags represent a significant reduction in memory usage

Although JVM implementations are certainly different, they are not always the case. > perform

My understanding is that the CPU is very digitally driven, and bitwise operation is as efficient as computing

Using bitwise operations for Boolean operations, is there a performance loss – or even gain? > succedaneum

Is there a better way to do the same thing? Enumeration allows the combination of flags, i.e. flagx = flag1 | Flag2?

Sample code

Note that the last method, propogatemove (), is recursive, can be called hundreds of times per second, and has a direct impact on the responsiveness of the application. Therefore, flags are used to avoid logical bits and calling other methods

// 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 @R_819_2419@ 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 (@R_819_2419@ 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 (@R_819_2419@ 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 @R_819_2419@ - 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 @R_819_2419@
    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;
}

Solution

Of course, it depends on the implementation of JVM, but the implementation of mainstream CPU may be correct

If you actually have 32 flags in a class, a large number of instances of that class are If you don't have more than a few hundred examples, don't worry

It's true.

It also depends on memory usage If you only use a few objects and are very focused, bitwise operation may slow down If you have many objects, reducing memory may improve performance due to better caching behavior

Instead of doing dot matrix operations yourself, you can (and should) use a BitSet Yes, it will be clearer if you can use enums and an enumset, but if you have many enums, it may not produce the required memory savings due to the overhead of multiple enumset instances

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>