VirtualBox

Changeset 22025 in vbox


Ignore:
Timestamp:
Aug 6, 2009 11:36:08 AM (15 years ago)
Author:
vboxsync
Message:

SSM: Detect zero pages in ssmR3DataWriteBig and store them using a 3 byte record instead of passing them on to LZF. LZF is kind of fast, but ASMMemIsZeroPage + memset is way faster.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/SSM-new.cpp

    r21952 r22025  
    102102 *                 field countining the length of the uncompressed data given in
    103103 *                 1KB units.
    104  *       - type 4: Named data - length prefixed name followed by the data. This
     104 *       - type 4: Zero data. The record header is followed by a 8-bit field
     105 *                 counting the length of the zero data given in 1KB units.
     106 *       - type 5: Named data - length prefixed name followed by the data. This
    105107 *                 type is not implemented yet as we're missing the API part, so
    106108 *                 the type assignment is tentative.
    107  *       - types 5 thru 15 are current undefined.
     109 *       - types 6 thru 15 are current undefined.
    108110 *   - bit 4: Important (set), can be skipped (clear).
    109111 *   - bit 5: Undefined flag, must be zero.
     
    208210/** Raw data compressed by LZF.
    209211 * The record header is followed by a 8-bit field containing the size of the
    210  * uncompressed data.  The compressed data is after it. */
     212 * uncompressed data in 1KB units.  The compressed data is after it. */
    211213#define SSM_REC_TYPE_RAW_LZF                    3
     214/** Raw zero data.
     215 * The record header is followed by a 8-bit field containing the size of the
     216 * zero data in 1KB units. */
     217#define SSM_REC_TYPE_RAW_ZERO                   4
    212218/** Named data items.
    213219 * A length prefix zero terminated string (i.e. max 255) followed by the data.  */
    214 #define SSM_REC_TYPE_NAMED                      4
     220#define SSM_REC_TYPE_NAMED                      5
    215221/** Macro for validating the record type.
    216222 * This can be used with the flags+type byte, no need to mask out the type first. */
     
    44304436    {
    44314437        /*
    4432          * Compress it if it's a page or more in size.
     4438         * Split it up into compression blocks.
    44334439         */
    44344440        for (;;)
    44354441        {
    4436             if (cbBuf >= SSM_ZIP_BLOCK_SIZE)
     4442            AssertCompile(SSM_ZIP_BLOCK_SIZE == PAGE_SIZE);
     4443            if (    cbBuf >= SSM_ZIP_BLOCK_SIZE
     4444                && (    ((uintptr_t)pvBuf & 0xf)
     4445                    ||  !ASMMemIsZeroPage(pvBuf))
     4446               )
    44374447            {
     4448                /*
     4449                 * Compress it.
     4450                 */
    44384451                AssertCompile(1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE < 0x00010000);
    44394452                uint8_t *pb;
     
    44744487                pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
    44754488            }
     4489            else if (cbBuf >= SSM_ZIP_BLOCK_SIZE)
     4490            {
     4491                /*
     4492                 * Zero block.
     4493                 */
     4494                uint8_t abRec[3];
     4495                abRec[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_ZERO;
     4496                abRec[1] = 1;
     4497                abRec[2] = SSM_ZIP_BLOCK_SIZE / _1K;
     4498                Log3(("ssmR3DataWriteBig: %08llx|%08llx/%08x: ZERO\n", ssmR3StrmTell(&pSSM->Strm) + 2, pSSM->offUnit + 2, 1));
     4499                rc = ssmR3DataWriteRaw(pSSM, &abRec[0], sizeof(abRec));
     4500                if (RT_FAILURE(rc))
     4501                    break;
     4502
     4503                /* advance */
     4504                if (cbBuf == SSM_ZIP_BLOCK_SIZE)
     4505                    return VINF_SUCCESS;
     4506                cbBuf -= SSM_ZIP_BLOCK_SIZE;
     4507                pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
     4508            }
    44764509            else
    44774510            {
     
    52345267    AssertLogRelMsgFailed(("cbCompr=%#x cbDecompr=%#x rc=%Rrc\n", cbCompr, cbDecompr, rc));
    52355268    return VERR_SSM_INTEGRITY_DECOMPRESSION;
     5269}
     5270
     5271
     5272/**
     5273 * Reads and checks the raw zero "header".
     5274 *
     5275 * @returns VBox status code.
     5276 * @param   pSSM            The saved state handle..
     5277 * @param   pcbDecompr      Where to store the size of the zero data.
     5278 */
     5279DECLINLINE(int) ssmR3DataReadV2RawZeroHdr(PSSMHANDLE pSSM, uint32_t *pcbZero)
     5280{
     5281    *pcbZero = 0; /* shuts up gcc. */
     5282    AssertLogRelMsgReturn(pSSM->u.Read.cbRecLeft == 1, ("%#x\n", pSSM->u.Read.cbRecLeft), VERR_SSM_INTEGRITY_DECOMPRESSION);
     5283
     5284    uint8_t cKB;
     5285    int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
     5286    if (RT_FAILURE(rc))
     5287        return rc;
     5288    pSSM->u.Read.cbRecLeft = 0;
     5289
     5290    uint32_t cbZero = (uint32_t)cKB * _1K;
     5291    AssertLogRelMsgReturn(cbZero <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
     5292                          ("%#x\n", cbZero), VERR_SSM_INTEGRITY_DECOMPRESSION);
     5293
     5294    *pcbZero = cbZero;
     5295    return VINF_SUCCESS;
    52365296}
    52375297
     
    54695529            case SSM_REC_TYPE_RAW_LZF:
    54705530            {
    5471                 uint32_t cbDecompr;
    5472                 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbDecompr);
     5531                int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
    54735532                if (RT_FAILURE(rc))
    54745533                    return rc;
    5475                 if (cbBuf >= cbDecompr)
     5534                if (cbToRead <= cbBuf)
    54765535                {
    5477                     cbToRead = cbDecompr;
    5478                     rc = ssmR3DataReadV2RawLzf(pSSM, pvBuf, cbDecompr);
     5536                    rc = ssmR3DataReadV2RawLzf(pSSM, pvBuf, cbToRead);
    54795537                    if (RT_FAILURE(rc))
    54805538                        return rc;
     
    54825540                else
    54835541                {
    5484                     /* output buffer is too small, use the data buffer. */
    5485                     rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbDecompr);
     5542                    /* The output buffer is too small, use the data buffer. */
     5543                    rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
    54865544                    if (RT_FAILURE(rc))
    54875545                        return rc;
     5546                    pSSM->u.Read.cbDataBuffer  = cbToRead;
    54885547                    cbToRead = (uint32_t)cbBuf;
     5548                    pSSM->u.Read.offDataBuffer = cbToRead;
    54895549                    memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToRead);
    5490                     pSSM->u.Read.cbDataBuffer  = cbDecompr;
    5491                     pSSM->u.Read.offDataBuffer = cbToRead;
    54925550                }
     5551                break;
     5552            }
     5553
     5554            case SSM_REC_TYPE_RAW_ZERO:
     5555            {
     5556                int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
     5557                if (RT_FAILURE(rc))
     5558                    return rc;
     5559                if (cbToRead > cbBuf)
     5560                {
     5561                    /* Spill the remainer into the data buffer. */
     5562                    memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead - cbBuf);
     5563                    pSSM->u.Read.cbDataBuffer  = cbToRead - cbBuf;
     5564                    pSSM->u.Read.offDataBuffer = 0;
     5565                    cbToRead = (uint32_t)cbBuf;
     5566                }
     5567                memset(pvBuf, 0, cbToRead);
    54935568                break;
    54945569            }
     
    55735648            case SSM_REC_TYPE_RAW_LZF:
    55745649            {
    5575                 uint32_t cbDecompr;
    5576                 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbDecompr);
     5650                int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
    55775651                if (RT_FAILURE(rc))
    55785652                    return rc;
    5579                 cbToRead = cbDecompr;
    55805653                rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
    55815654                if (RT_FAILURE(rc))
    55825655                    return rc;
     5656                pSSM->u.Read.cbDataBuffer = cbToRead;
     5657                break;
     5658            }
     5659
     5660            case SSM_REC_TYPE_RAW_ZERO:
     5661            {
     5662                int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
     5663                if (RT_FAILURE(rc))
     5664                    return rc;
     5665                memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead);
    55835666                pSSM->u.Read.cbDataBuffer = cbToRead;
    55845667                break;
  • trunk/src/VBox/VMM/testcase/tstSSM.cpp

    r21893 r22025  
    9191        memcpy(pb, szTmp, 16);
    9292    }
     93
     94    /* add some zero pages */
     95    memset(&gabBigMem[sizeof(gabBigMem) / 4],     0, PAGE_SIZE * 4);
     96    memset(&gabBigMem[sizeof(gabBigMem) / 4 * 3], 0, PAGE_SIZE * 4);
    9397#endif
    9498}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette