Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Fast serialization

Fast serialization

Scheduled Pinned Locked Moved C / C++ / MFC
iosjsonhelptutorialquestion
13 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Budric B
    wrote on last edited by
    #1

    Hi, I need very fast serialization to disk of a large object (64 MB/128 MB etc). Serializing members one by one is not an option (Boost serialization for example is very slow), and the object does need to be shared across systems so I don't need to worry about endianness. Here's what I came up with:

    void saveVoxels(Voxels * voxelData, const char * fileName) throw(...)
    {
    using namespace std;
    ofstream file (fileName, ios::out | ios::binary);
    if (file.is_open())
    {
    file.write((char *)voxelData, sizeof(Voxels));
    unsigned int size = voxelData->m_sliceWidth * voxelData->m_sliceHeight * voxelData->m_numSlices * sizeof(unsigned short);
    file.write((char *)voxelData->m_pTexture, size);
    file.close();
    }
    }
    Voxels* loadVoxels(const char * fileName) throw(...)
    {
    using namespace std;
    ifstream file(fileName, ios::in | ios::binary | ios::ate);
    if (file.is_open())
    {
    unsigned long size = file.tellg();
    char * memblock = new char [size];
    file.seekg (0, ios::beg);
    file.read (memblock, size);
    file.close();

    	//initialize
    	Voxels \* voxelData = (Voxels \*) memblock;
    	voxelData->m\_pTexture = (unsigned short \*) (memblock + sizeof(Voxels));
    	return voxelData;
    }
    

    }

    Which as far as I can tell works. However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error. I guess I didn't really allocate the m_pTexture pointer which is what gets deleted...Any solutions?

    E D M L N 5 Replies Last reply
    0
    • B Budric B

      Hi, I need very fast serialization to disk of a large object (64 MB/128 MB etc). Serializing members one by one is not an option (Boost serialization for example is very slow), and the object does need to be shared across systems so I don't need to worry about endianness. Here's what I came up with:

      void saveVoxels(Voxels * voxelData, const char * fileName) throw(...)
      {
      using namespace std;
      ofstream file (fileName, ios::out | ios::binary);
      if (file.is_open())
      {
      file.write((char *)voxelData, sizeof(Voxels));
      unsigned int size = voxelData->m_sliceWidth * voxelData->m_sliceHeight * voxelData->m_numSlices * sizeof(unsigned short);
      file.write((char *)voxelData->m_pTexture, size);
      file.close();
      }
      }
      Voxels* loadVoxels(const char * fileName) throw(...)
      {
      using namespace std;
      ifstream file(fileName, ios::in | ios::binary | ios::ate);
      if (file.is_open())
      {
      unsigned long size = file.tellg();
      char * memblock = new char [size];
      file.seekg (0, ios::beg);
      file.read (memblock, size);
      file.close();

      	//initialize
      	Voxels \* voxelData = (Voxels \*) memblock;
      	voxelData->m\_pTexture = (unsigned short \*) (memblock + sizeof(Voxels));
      	return voxelData;
      }
      

      }

      Which as far as I can tell works. However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error. I guess I didn't really allocate the m_pTexture pointer which is what gets deleted...Any solutions?

      E Offline
      E Offline
      El Corazon
      wrote on last edited by
      #2

      have you tried something like: KLV?[^]. It is just a form of binary serialization, but we shoot videos to file or across the net using it.

      _________________________ Asu no koto o ieba, tenjo de nezumi ga warau. Talk about things of tomorrow and the mice in the ceiling laugh. (Japanese Proverb)

      1 Reply Last reply
      0
      • B Budric B

        Hi, I need very fast serialization to disk of a large object (64 MB/128 MB etc). Serializing members one by one is not an option (Boost serialization for example is very slow), and the object does need to be shared across systems so I don't need to worry about endianness. Here's what I came up with:

        void saveVoxels(Voxels * voxelData, const char * fileName) throw(...)
        {
        using namespace std;
        ofstream file (fileName, ios::out | ios::binary);
        if (file.is_open())
        {
        file.write((char *)voxelData, sizeof(Voxels));
        unsigned int size = voxelData->m_sliceWidth * voxelData->m_sliceHeight * voxelData->m_numSlices * sizeof(unsigned short);
        file.write((char *)voxelData->m_pTexture, size);
        file.close();
        }
        }
        Voxels* loadVoxels(const char * fileName) throw(...)
        {
        using namespace std;
        ifstream file(fileName, ios::in | ios::binary | ios::ate);
        if (file.is_open())
        {
        unsigned long size = file.tellg();
        char * memblock = new char [size];
        file.seekg (0, ios::beg);
        file.read (memblock, size);
        file.close();

        	//initialize
        	Voxels \* voxelData = (Voxels \*) memblock;
        	voxelData->m\_pTexture = (unsigned short \*) (memblock + sizeof(Voxels));
        	return voxelData;
        }
        

        }

        Which as far as I can tell works. However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error. I guess I didn't really allocate the m_pTexture pointer which is what gets deleted...Any solutions?

        D Offline
        D Offline
        David Crow
        wrote on last edited by
        #3

        Budric B. wrote:

        However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error.

        Does the pointer ever get moved? In other words, if you did something like:

        char *p = new char[5];
        p++;
        delete [] p;

        the result would not be what you'd expect because a different address is being freed.


        "A good athlete is the result of a good and worthy opponent." - David Crow

        "To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne

        B 1 Reply Last reply
        0
        • D David Crow

          Budric B. wrote:

          However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error.

          Does the pointer ever get moved? In other words, if you did something like:

          char *p = new char[5];
          p++;
          delete [] p;

          the result would not be what you'd expect because a different address is being freed.


          "A good athlete is the result of a good and worthy opponent." - David Crow

          "To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne

          B Offline
          B Offline
          Budric B
          wrote on last edited by
          #4

          No, the pointers does not get moved. Voxels is a class and it gets returned from the loadVoxels() function. The problem is when I call "delete Voxels;" the destructor is deleting the member array and that's when the assertion fails.

          D 1 Reply Last reply
          0
          • B Budric B

            No, the pointers does not get moved. Voxels is a class and it gets returned from the loadVoxels() function. The problem is when I call "delete Voxels;" the destructor is deleting the member array and that's when the assertion fails.

            D Offline
            D Offline
            David Crow
            wrote on last edited by
            #5

            Budric B. wrote:

            The problem is when I call "delete Voxels;"...

            Which should be:

            delete [] Voxels;


            "A good athlete is the result of a good and worthy opponent." - David Crow

            "To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne

            B 1 Reply Last reply
            0
            • D David Crow

              Budric B. wrote:

              The problem is when I call "delete Voxels;"...

              Which should be:

              delete [] Voxels;


              "A good athlete is the result of a good and worthy opponent." - David Crow

              "To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne

              B Offline
              B Offline
              Budric B
              wrote on last edited by
              #6

              I see...even though it's an object? I know I'm casting an array to an object, but I would have thought things would behave as they would for any object created with new.

              D 1 Reply Last reply
              0
              • B Budric B

                Hi, I need very fast serialization to disk of a large object (64 MB/128 MB etc). Serializing members one by one is not an option (Boost serialization for example is very slow), and the object does need to be shared across systems so I don't need to worry about endianness. Here's what I came up with:

                void saveVoxels(Voxels * voxelData, const char * fileName) throw(...)
                {
                using namespace std;
                ofstream file (fileName, ios::out | ios::binary);
                if (file.is_open())
                {
                file.write((char *)voxelData, sizeof(Voxels));
                unsigned int size = voxelData->m_sliceWidth * voxelData->m_sliceHeight * voxelData->m_numSlices * sizeof(unsigned short);
                file.write((char *)voxelData->m_pTexture, size);
                file.close();
                }
                }
                Voxels* loadVoxels(const char * fileName) throw(...)
                {
                using namespace std;
                ifstream file(fileName, ios::in | ios::binary | ios::ate);
                if (file.is_open())
                {
                unsigned long size = file.tellg();
                char * memblock = new char [size];
                file.seekg (0, ios::beg);
                file.read (memblock, size);
                file.close();

                	//initialize
                	Voxels \* voxelData = (Voxels \*) memblock;
                	voxelData->m\_pTexture = (unsigned short \*) (memblock + sizeof(Voxels));
                	return voxelData;
                }
                

                }

                Which as far as I can tell works. However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error. I guess I didn't really allocate the m_pTexture pointer which is what gets deleted...Any solutions?

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #7

                I'm probably wrong, but at first glabce something seems fishy here.... When you write you do this

                file.write((char *)voxelData->m_pTexture, size);

                When you read you do this Voxels * voxelData = (Voxels *) memblock;
                voxelData->m_pTexture = (unsigned short *) (memblock + sizeof(Voxels));
                Is there a discrepancy there? Mark

                Mark Salsbery Microsoft MVP - Visual C++ :java:

                B 1 Reply Last reply
                0
                • B Budric B

                  Hi, I need very fast serialization to disk of a large object (64 MB/128 MB etc). Serializing members one by one is not an option (Boost serialization for example is very slow), and the object does need to be shared across systems so I don't need to worry about endianness. Here's what I came up with:

                  void saveVoxels(Voxels * voxelData, const char * fileName) throw(...)
                  {
                  using namespace std;
                  ofstream file (fileName, ios::out | ios::binary);
                  if (file.is_open())
                  {
                  file.write((char *)voxelData, sizeof(Voxels));
                  unsigned int size = voxelData->m_sliceWidth * voxelData->m_sliceHeight * voxelData->m_numSlices * sizeof(unsigned short);
                  file.write((char *)voxelData->m_pTexture, size);
                  file.close();
                  }
                  }
                  Voxels* loadVoxels(const char * fileName) throw(...)
                  {
                  using namespace std;
                  ifstream file(fileName, ios::in | ios::binary | ios::ate);
                  if (file.is_open())
                  {
                  unsigned long size = file.tellg();
                  char * memblock = new char [size];
                  file.seekg (0, ios::beg);
                  file.read (memblock, size);
                  file.close();

                  	//initialize
                  	Voxels \* voxelData = (Voxels \*) memblock;
                  	voxelData->m\_pTexture = (unsigned short \*) (memblock + sizeof(Voxels));
                  	return voxelData;
                  }
                  

                  }

                  Which as far as I can tell works. However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error. I guess I didn't really allocate the m_pTexture pointer which is what gets deleted...Any solutions?

                  L Offline
                  L Offline
                  led mike
                  wrote on last edited by
                  #8

                  What is the reason that you do not have save/load as members of the Voxel class that then manages the internal char* ??

                  1 Reply Last reply
                  0
                  • B Budric B

                    Hi, I need very fast serialization to disk of a large object (64 MB/128 MB etc). Serializing members one by one is not an option (Boost serialization for example is very slow), and the object does need to be shared across systems so I don't need to worry about endianness. Here's what I came up with:

                    void saveVoxels(Voxels * voxelData, const char * fileName) throw(...)
                    {
                    using namespace std;
                    ofstream file (fileName, ios::out | ios::binary);
                    if (file.is_open())
                    {
                    file.write((char *)voxelData, sizeof(Voxels));
                    unsigned int size = voxelData->m_sliceWidth * voxelData->m_sliceHeight * voxelData->m_numSlices * sizeof(unsigned short);
                    file.write((char *)voxelData->m_pTexture, size);
                    file.close();
                    }
                    }
                    Voxels* loadVoxels(const char * fileName) throw(...)
                    {
                    using namespace std;
                    ifstream file(fileName, ios::in | ios::binary | ios::ate);
                    if (file.is_open())
                    {
                    unsigned long size = file.tellg();
                    char * memblock = new char [size];
                    file.seekg (0, ios::beg);
                    file.read (memblock, size);
                    file.close();

                    	//initialize
                    	Voxels \* voxelData = (Voxels \*) memblock;
                    	voxelData->m\_pTexture = (unsigned short \*) (memblock + sizeof(Voxels));
                    	return voxelData;
                    }
                    

                    }

                    Which as far as I can tell works. However when deleting the object I get _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) assertion error. I guess I didn't really allocate the m_pTexture pointer which is what gets deleted...Any solutions?

                    N Offline
                    N Offline
                    Nathan Holt at EMOM
                    wrote on last edited by
                    #9

                    I get the impresion that Voxels is an object with actual behavior, and therefore shouldn't be written to a file like that. Things like virtual function table pointers can't be saved and restored that way. Also, it looks like Voxels is a relatively small object with a pointer to a huge array, so you wouldn't lose much performance by saving the simple members of Voxels individually. I would save the simple members of Voxels first and then save the array with one file.write call. To restore it, I'd create a Voxels object, read the simple members, and then allocate and read the array. Also, I noticed you are using unsigned int for the size to write to the file. If you use size_t, the type will be adjusted properly if you migrate to a 64 bit system. Nathan

                    B 1 Reply Last reply
                    0
                    • B Budric B

                      I see...even though it's an object? I know I'm casting an array to an object, but I would have thought things would behave as they would for any object created with new.

                      D Offline
                      D Offline
                      David Crow
                      wrote on last edited by
                      #10

                      Well, it wouldn't hurt to try. If it doesn't work, you're no worse off.


                      "A good athlete is the result of a good and worthy opponent." - David Crow

                      "To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne

                      1 Reply Last reply
                      0
                      • M Mark Salsbery

                        I'm probably wrong, but at first glabce something seems fishy here.... When you write you do this

                        file.write((char *)voxelData->m_pTexture, size);

                        When you read you do this Voxels * voxelData = (Voxels *) memblock;
                        voxelData->m_pTexture = (unsigned short *) (memblock + sizeof(Voxels));
                        Is there a discrepancy there? Mark

                        Mark Salsbery Microsoft MVP - Visual C++ :java:

                        B Offline
                        B Offline
                        Budric B
                        wrote on last edited by
                        #11

                        No, I first write the object, which contains the data members and a pointer at the end. The size of the object is sizeof(Voxels). I then write the array of stuff. When I read, I read everything. I know that the first sizeof(Voxels) bytes is the object including a pointer with a value that's meaningless. I then assign the pointer to point to the data, which just happens to be right after the object (because that's where I read it into).

                        1 Reply Last reply
                        0
                        • N Nathan Holt at EMOM

                          I get the impresion that Voxels is an object with actual behavior, and therefore shouldn't be written to a file like that. Things like virtual function table pointers can't be saved and restored that way. Also, it looks like Voxels is a relatively small object with a pointer to a huge array, so you wouldn't lose much performance by saving the simple members of Voxels individually. I would save the simple members of Voxels first and then save the array with one file.write call. To restore it, I'd create a Voxels object, read the simple members, and then allocate and read the array. Also, I noticed you are using unsigned int for the size to write to the file. If you use size_t, the type will be adjusted properly if you migrate to a 64 bit system. Nathan

                          B Offline
                          B Offline
                          Budric B
                          wrote on last edited by
                          #12

                          It doesn't have that much behavior other than a constructor and a destructor to free the memory. The reason I was doing it this way was because I would be adding more data members to describe the data later. But you're probably right that it wouldn't add that much performance loss to write each data member. I'll have to time it and see. I've made a workaround where I allocate 2 buffers, 1 for the object and one for the data, the rest of the code stays the same. That doesn't trigger the assertion. However I don't know if the object's memory gets freed or not since I'm still calling delete Voxels and not delete [] voxels;

                          N 1 Reply Last reply
                          0
                          • B Budric B

                            It doesn't have that much behavior other than a constructor and a destructor to free the memory. The reason I was doing it this way was because I would be adding more data members to describe the data later. But you're probably right that it wouldn't add that much performance loss to write each data member. I'll have to time it and see. I've made a workaround where I allocate 2 buffers, 1 for the object and one for the data, the rest of the code stays the same. That doesn't trigger the assertion. However I don't know if the object's memory gets freed or not since I'm still calling delete Voxels and not delete [] voxels;

                            N Offline
                            N Offline
                            Nathan Holt at EMOM
                            wrote on last edited by
                            #13

                            Budric B. wrote:

                            It doesn't have that much behavior other than a constructor and a destructor to free the memory. The reason I was doing it this way was because I would be adding more data members to describe the data later. But you're probably right that it wouldn't add that much performance loss to write each data member. I'll have to time it and see.

                            Watch out for the copy constructor and assignment operator, since the compiler will generate invalid forms and call them freely.

                            Budric B. wrote:

                            I've made a workaround where I allocate 2 buffers, 1 for the object and one for the data, the rest of the code stays the same. That doesn't trigger the assertion. However I don't know if the object's memory gets freed or not since I'm still calling delete Voxels and not delete [] voxels;

                            I think that should work. The main difference between delete and delete[] is the way destructors are called, which shouldn't be a problem if it's just data. Nathan

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups