|
|
Comments and Discussions
|
|
 |

|
Just tried to serialize a class to a file, using the showed method.
it serialized just fine.. but it failed on the read phase!
Then I did serialize a single integer number (int32) towards a file stream, and it fails!
Did all the steps as you show here, but instead of using a MemoryStream class I used a FileStream class
it also serialized just fine.. but it fails on the read phase!
The system returns zero valued integers,
as I inspect the file... it has a large zero header '00' bytes
I just needed to serialize a large BitArray, in a compressed way.
BinarySerializer just works fine, but generates a extremly large file!
any clue?
Andres
|
|
|
|

|
Hi Andres
Off the top of my head:
The first 4 bytes are used to store the size of the compressed data where the stream is seekable.
Both FileStream and MemoryStream are seekable so this value should be updated at the end of serialization.
So either nothing was serialized at all (in which case you would have a file containing a single 0 int32 value);
or maybe you didn't close the stream so the header wasn't updated. Though I would have thought it would still deserialize provided the stream was rewound.
If you want to post the exact code you were using, maybe the problem will become clearer.
Cheers
Simon
|
|
|
|

|
I havent realize that I had to call the Update-[rpcedure:
writer.UpdateHeader();
prior to calling
writer.Close();
¿Shouldn't this be internally tied to a conditional (bool flag : allowUpdateHeader )?
Except from that, issue solved!
cheers! (good job)
|
|
|
|

|
Fantastic! Allowed us to drop our load/save times from 30 seconds to milliseconds. Top job!
|
|
|
|
|

|
Very thorough and well designed.
|
|
|
|

|
Hi Simon,
Happy to see you're still improving your lib. I've made a couple of improvments/bug fixs that you may be interested in - if so, give me an email so that I can send them to you (list updated on 2011/07/28):
- Renamed interface to something shorter: IOwnedDataSerializable => ISelfSerializable
- Removed useless interface IOwnedDataSerializableAndRecreatable (functionality unchanged but interface actually not needed)
- Added possibility to use a different constructor when needed via interface ISelfSerializableWithCustomConstructor
- Added possibility of version handling when deserializing via interface ISelfSerializableWithCustomConstructorAndVersionHandling
- Updated the code to internally manage a few other .NET types we daily use: Guid, IPAddress…
- Added a IFastSerializationTypeSurrogate which inherits from ISelfSerializable. This allows you to easily declare types fast serialized, and this quicker than by using IFastSerializationTypeCodeSurrogate (which we don’t use as we think it’s too heavy). I let also a few code using a custom type of ours (IMessage) to see how you can use it to extend it further – you can remove it if you want.
- Write(List) and Writes(Dictionary) now handles null list/dico
- Better type optimization when handling arrays (and list, dico, etc.), ie better ability to detect if should serialize the kind of each item or once for the whole collection
- Better Write(Type) - 4 kinds identified + one-self discovery to know what to serialize for a Type.
- bug fixed: implementing Dispose(bool) + allow not to dispose base stream if requested
- Writing/reading enum array in an optimized fashion
- Speed improvment by avoiding as much as possible to call GetType method (which is very slow).
- ... (can't remember everything)
Regards and many thanks for the lib we've been (happily) using for 3 years now.
Chris
Chris
www.aulofee.com - Infrastructure and Security Supervision, Event Correlation
modified on Thursday, July 28, 2011 4:46 AM
|
|
|
|

|
First I would like to thank you for such a fine piece of work and contributing it to the public domain. I really appreciate it.
The Bug: By writing the tokenized Strings and Objects inline you are forcing every string or object to be read from the serialized stream when deserializing. One of the techniques I often use with serialization is to write shortcuts for sections of the stream when it is unnecessary to read everything from the stream because I already have all of the data in hand due to either version match or a match on a hash...this avoids allot of unnecessary work and can significantly decrease deserialization time.
Unfortunately, if you don't read every string your token list positions don't match what was serialized and thus you get an out of range error. It is not as simple as expanding the token list to accommodate newly read tokens, because some of the string values you are looking for later on in the stream may have been one of the orphaned values that were skipped.
I don't really see any way around this problem other than going back to appending the token lists at the end of the serialization.
Any feedback is appreciated.
Regards
Dru
|
|
|
|

|
Hi Dru
Not really a bug.
What you are talking about is different functionality.
Cheers
Simon
|
|
|
|

|
I agree with you, "bug" is not the appropriate label. I am really commenting on the architecture of inline vs. appending the lists to the end. I don't see any advantages to inline, only disadvantages as already described....my 2 cents
In the mean time, I took your most recent code and changed it back to appending the token tables to the end of the stream. Additionally, I added a static header to the stream so that serialized bytes from your serializer can be recognized programmatically. Part of this header also contains a version number to indicate the binary version of the serializer in case the binary representation of anything needs to change. Lastly, I added a required int32 parameter to all constructors so that the programmer is forced to provide an identifier for the data they are about to stream (becomes a property on the reader)....this way, the programmer is forced to consider how they will recognize various serialized formats for their use and have easy paths to support different serialized objects. Lastly, I always suggest that each object that streams uses version numbers in the stream so that they can support multiple storage versions to avoid mass conversions of previously serialized data…I usually only serialize the most recent format, but support all older versions for deserialzation.
These are all simple suggestions that I have found useful for those who serialize and persist.
Once again, thank you for the great code and the great article
Cheers!
Dru
|
|
|
|

|
Hi Dru
There was a reason for changing to inline storage rather than appending and that was to allow non-seekable streams to be used. For instance, a zip-based stream.
Also, the code was specifically designed for non-persistence use, just for remoting.
I'm glad you've developed a way of integrating versioning into the code. Maybe you could write an article showing how in more detail?
Cheers
Simon
|
|
|
|

|
This is really great work. I was looking to improve the performance for Serialization and this works great. The timing is gone down but the size is huge. See below the code:
For testing, I've created a small class with four propertied. Created 1 million objects of this class and serialized it using both methods.
BinaryFormatter size was 67,108,864
SerializeWriter size was 134,217,728
As you can see it is almost double.
Please let me know if I am doing anything wrong. I've tried Optimized methods as well but same result.
[Serializable]
public class DataObject
{
public string Prop1 { get; set; }
public bool Prop2 { get; set; }
public DateTime Prop3 { get; set; }
public DateTime Prop4 { get; set; }
public DataObject()
{
}
}
private void DoWork()
{
for (int i = 0; i < 1000000; i++)
_objs.Add(new DataObject() { Prop1 = "Test", Prop2 = false, Prop3 = DateTime.Now, Prop4 = DateTime.UtcNow });
long _len1 = 0;
long _len2 = 0;
using (MemoryStream ms = new MemoryStream())
{
new BinaryFormatter().Serialize(ms, _objs);
_len1 = ms.GetBuffer().Length;
ms.Seek(0, 0);
new BinaryFormatter().Deserialize(ms);
}
Framework.Serialization.SerializationWriter writer = new Framework.Serialization.SerializationWriter();
writer.Write<DataObject>(_objs);
byte[] _data = writer.ToArray();
_len2 = _data.Length;
writer.Close();
Framework.Serialization.SerializationReader reader = new Framework.Serialization.SerializationReader(_data);
List<DataObject> __objs = reader.ReadList<DataObject>();
}
}
|
|
|
|

|
FastSerializer is not a general replacement for BinaryFormatter.
It is designed to allow *you the programmer* to store your data in a more compact format and do it quicker.
For example, if your test class had been written:-
[Serializable]
public class DataObject: IOwnedDataSerializableAndRecreatable
{
public string Prop1 { get; set; }
public bool Prop2 { get; set; }
public DateTime Prop3 { get; set; }
public DateTime Prop4 { get; set; }
public DataObject()
{
}
public void SerializeOwnedData(SerializationWriter writer, object context)
{
writer.WriteOptimized(Prop1);
writer.Write(Prop2);
writer.Write(Prop3);
writer.Write(Prop4);
}
public void DeserializeOwnedData(SerializationReader reader, object context)
{
Prop1 = reader.ReadOptimizedString();
Prop2 = reader.ReadBoolean();
Prop3 = reader.ReadDateTime();
Prop4 = reader.ReadDateTime();
}
}
Then the size would have been 19,000,021 bytes.
As it happens, your test class is not the easiest to optimize. The string will only be stored once, but there aren't many savings with a bool! And your two datetimes are stored to sub-millisecond accuracy and so will be 7 bytes each (still saving a byte each over the normal 8).
If you didn't store the milliseconds on your DateTimes, then the size would be 15,000,021.
If you really wanted to store both the Local and Utc versions of a time then you could skip storing Prop4 in SerializeOwnedData and just create it in DeserializeOwnedData: e.g. Prop4 = TimeZoneInfo.ConvertTimeToUtc(Prop3); which would then take just 9,000,021 bytes.
Cheers
Simon
|
|
|
|

|
Thanks for the quick reply. Changes you made worked! The size is much smaller then binary formatter.
One more question: Is there any way I could use this to replace serialization for WCF?
The output size from Fast serializer is much smaller then either BinaryFormatter or DataContractSerializer.
Thanks,
|
|
|
|

|
Great article well done. Any ideas when the LlblGenPro serialization will/might be online?
Thanks
|
|
|
|

|
Its already baked directly into LLBLGEN - was done some years ago
Cheers
Simon
|
|
|
|

|
Hi Guys,
Please excuse me if this question has an obvious answer but can you please tell me what happened to the support for ICollection in the Write(); method?
Thanks in advance
Dave
|
|
|
|

|
Hi Simon,
I ported your Fast Serializer to the Compact Framework.
Instead of using BinaryFormatter, OtherType is handled internally now.
As I don't needed some features, I removed:
- SingleInstanceType
- OwnedDataSerializableAndRecreatableType
Also all OtherType and SurrogateHandledType are handled as tokenized objects.
The source is on codeplex: Fast Compact Serializer
I would be happy to hear from you.
Regards,
tibel
|
|
|
|

|
Hi,
i've been using your code for quite some time, and up until now without any issues.
When working with BinaryFormatter, i'm able to serialize and de-serialize using your great fast serializer code, however i can't seem to be able to use it when working with DataContractSerializer.
the following code snippet works with the fast serializer:
BinaryFormatter bformatter = new BinaryFormatter();
bformatter.Serialize(stream, dataset);
stream.Close();
bformatter = new BinaryFormatter();
TDataSetType newDs = (TDataSetType)bformatter.Deserialize(stream);
stream.Close();
the following code does not work with the fast serializer:
DataContractSerializer dcSerializer = new DataContractSerializer(typeof(TDataSetType));
dcSerializer.WriteObject(stream, dataset);
stream.Close();
dcSerializer = new DataContractSerializer(typeof(TDataSetType));
TDataSetType newDs = (TDataSetType)dcSerializer.ReadObject(stream);
stream.Close();
What should i do in order to step into the Fast Serializer, also when using the DataContractSerializer (as oppose to the BinaryFormatter)?
Thanks!
|
|
|
|

|
Dear Simon,
How multi-dimensional arrays (like object[,]) are supposed to be serialized using your framework?
Thanks, Boris.
|
|
|
|

|
Hi Simon,
Thank you for this library.
I slightly improved it for my project by adding an optional context parameter to all the reading/writing methods that work with collections, and also to Read/WriteObject. In case when one or more of the collection items represent IOwnedDataSerializable, the non-null context would be passed to the appropriate method.
public List<T> ReadList<T>(object context = null)
{
return new List<T>((T[]) ProcessArrayTypes(ReadTypeCode(), typeof(T), context));
}
var result = Array.CreateInstance(defaultElementType, length);
for (var i = 0; i < length; i++)
{
if (optimizeFlags == null)
{
result.SetValue(ReadObject(context), i);
}
else if ((optimizeFlags == FullyOptimizableTypedArray) || !optimizeFlags[i])
{
var value = (IOwnedDataSerializable) Activator.CreateInstance(defaultElementType);
ReadOwnedData(value, context);
result.SetValue(value, i);
}
}
Regards, Boris
|
|
|
|

|
Hi.
I'm trying to serialize a large array of data (about 20 million items, each one is a struct of a double and a short List).
By my calculations the minimum file size should be about 600MB without overhead, so I expect about 800-1000MB with overhead.
However, when serializing using FastSerializer v2.1 the memory usage reaches the system's physical memory limits, and then a swapping party begins and the program and computer slow to a crawl.
By my understanding this is caused because of the usage of MemoryStream as the serialization target, which only writes to disk when the SerializationWriter object is destroyed.
Is there a way to flush the data periodically to disk?
Set an upper limit to memory usage of FastSerializer?
Another option is to create a new SerializationWriter whenever the program reaches a certain amount of memory usage - but I think will this create problems with the SerializationReader.
Solutions?
Thanks,
Haggai
|
|
|
|

|
Hi Haggai
The latest version allows any stream to be used so you could try using a file stream.
I don't have any test data of that size but if you wanted to provide me with some I don't mind trying it out.
Cheers
Simon
|
|
|
|

|
Hi - thanks for the excellent code, first of all.
I seem to have hit an issue with using WriteTokenizedObject on an instance of IOwnedDataSerializableAndRecreatable. The problem specifically seems to be that the Writer in AppendTokenTables writes the stringLookup list and then the objectToken list:
int stringTokensCount = stringLookup.Count;
write7bitEncodedSigned32BitValue(stringLookup.Count);
for(int i = 0; i < stringTokensCount; i++)
{
base.Write(stringLookup[i]);
}
write7bitEncodedSigned32BitValue(objectTokens.Count);
for (int i = 0; i < objectTokens.Count; i++)
{
WriteObject(objectTokens[i]);
}
However, the WriteObject call adds new strings to the lookup, which don't get written to the the stream (since this ship has already sailed...). I tried switching the order (in the reader and writer) but this just introduces a new bug in the Reader constructor since reading the objectTokens relies on a populated stringLookup list...
Any ideas?
|
|
|
|

|
Hi
Could you write a test case for this issue - nothing major, just one Test method and a simple IOwnedDataSerializableAndRecreateable to specifically highlight the bug.
If you can do that, I'll make time to find a solution and update the article.
(I *think* that the slightly tweaked version I wrote that was incorporated into LLBLGenPro wrote the tokens inline rather than en-bloc at the end of the stream and that should solve the problem.)
Cheers
Simon
|
|
|
|

|
Hi
See here:
http://dl.dropbox.com/u/4696217/FastSerialization.rar
BugTest.CannotWriteAndReadTokenisedObjects
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at SimmoTech.Utils.Serialization.SerializationReader.readTokenizedString(Int32 bucket) in FastSerializer.cs: line 4849
Note also that I do now have a potential fix for this:
http://dl.dropbox.com/u/4696217/FastSerialization.patch
Basically writing the strings after the tokenised objects but reading them first (uses a similar approach used for writing the tokenTables as a whole)
|
|
|
|

|
Couldn't you write the object list first during serialization(as you already tried), but read the string token list first during deserialization...all it would take is writing the two offsets for the lists before writing the lists so they two offsets could be read in different order during deserialization.
|
|
|
|

|
i understand that the main purpose of this development was for remoting.
but what happens if i want to use this for files?
what happens if tomorrow my variables changes??
there's no real way to check if the data is there or not...
are there any solutions for that?
Don't believe to what you hear on the news...
|
|
|
|

|
I've not used this code for anything other than remoting but I don't see why you couldn't write a byte as a 'version' code and the deserializer could decide what to do based on this.
Cheers
Simon
|
|
|
|

|
Hi Simon,
First a big thank for the library. I was using pointer and unsafe code (in c#) to go even faster that yours, but the coding was a little tedious...
My small improvment was to make the constructors "SerializationWriter/Read(Stream)" public. This allows me to write everything I need for my class without uslessly duplicating/copying data. I think this can be useful to others.
The bug this created was that AppendTokenTables and the constructor of the SerializationReader consider that you start at position 0 of the stream. A little change allows your code to be 100% "generic" and so to use an existing stream:
public int AppendTokenTables()
{
long currentPosition = BaseStream.Position;
BaseStream.Position = _startPosition;
Write((int)(currentPosition - _startPosition)); BaseStream.Position = currentPosition;
[...]
}
public SerializationReader(Stream stream)
: base(stream)
{
if (!stream.CanSeek) throw new InvalidOperationException("Stream must be seekable");
_startPosition = stream.Position;
int tokenTablePositionOffset = ReadInt32();
_tokenTablePosition = (int)_startPosition + tokenTablePositionOffset;
stream.Position = _tokenTablePosition;
[...]
}
I also created a new interface IOwnedDataSerializableAndRecreatableWithCustomConstructor which inherits from IOwnedDataSerializableAndRecreatable, and which allows to use a constructor which is not the default parameterless one but a one specific for the deserialization (sometimes, the public parameterless constructor performs some actions you don't want at deserialization). If anybody is interested, just email me.
Thanks again for your code, Simon, and I hope you'll keep improving it.
Chris
Chris
www.aulofee.com - Infrastructure and Security Supervision, Event Correlation
|
|
|
|

|
Great Can you do a Silverlight Version of it ?
Thanx for this great utility
|
|
|
|

|
In the article - part 1:
"you've every used" -> "you've ever used" ?
Regards,
Peter Mortensen
|
|
|
|

|
What am I missing here? There is a SerializationWriter.Write method that takes a float, but no SerializationReader.ReadFloat() method!?
|
|
|
|

|
SerializationReader inherits BinaryReader and there is a ReadSingle() method on there.
Cheers
Simon
|
|
|
|

|
Thanks!! My "light" simulation runs were taking about 30MB for a light run, now its down to 4.9MB! (there are thousands of "heavy" runs for statistical reasons). I was hoping for a better decrease in storage space required, but this is plenty. It's also wicked fast (which is more important, I will play with OptimizeForSize later). And I like the API. Solid work!
|
|
|
|

|
Glad its going well so far.
Unfortunately, I don't think there are optimizations for floats and doubles.
I suppose you may be able to do something special if there are specific exact values that come up many times or if sets of values are identical but other than that it will always be 4 bytes/single and 8 bytes/double.
Cheers
Simon
Cheers
Simon
|
|
|
|

|
Object --> Dictionary --> (string,subobject)
^ |
|____________________________<
An objectA having a dictionary with string as key and a objectB as value, the objectB has reference to the objectA (the same one which contains the dictionary containing the objectB)
Any help would be appreciated?
|
|
|
|

|
I have been using your library for my 32-bit remoting application, it works great. Thanks for the excellent work.
My only question is, can the library be compiled to 64-bit application? and how?
Best regards,
Bing
|
|
|
|

|
Dear Simon, Thanks for the article, it is very good code, there is no sample about IOwnedDataSerializableAndRecreatable, Would you please have a look to the flowing code, just to be sure I have implement it in the right way, thanks is advance, awaiting for your notes.
class erpcolumn : IOwnedDataSerializableAndRecreatable { public string name; public int type; public int size; public void SerializeOwnedData(SerializationWriter writer, object context) { writer.Write(name); writer.Write(type); writer.Write(size); } public void DeserializeOwnedData(SerializationReader reader, object context) { name = reader.ReadString(); type = reader.ReadInt32(); size = reader.ReadInt32(); } } [Serializable] class erptable : ISerializable { public erptable() {} public erpcolumn[] columns; public string name = ""; public int noofcolumns = 0; public erpcolumn firstcol; public Dictionary<string, erpcolumn> d1 = new Dictionary<string,erpcolumn>(); public void GetObjectData(SerializationInfo info, StreamingContext ctxt) { SerializationWriter writer = new SerializationWriter(2048); writer.OptimizeForSize = false; writer.Write(name); writer.Write(noofcolumns); writer.WriteObject(firstcol); writer.WriteTypedArray(columns); writer.Write<string, erpcolumn>(d1); info.AddValue("data", writer.ToArray()); } public erptable(SerializationInfo info, StreamingContext ctxt) { SerializationReader reader = new SerializationReader((byte[]) info.GetValue("data", typeof(byte[]))); name = reader.ReadString(); noofcolumns = reader.ReadInt32(); firstcol = (erpcolumn)reader.ReadObject(); columns = (erpcolumn[])reader.ReadTypedArray(); d1 = reader.ReadDictionary<string, erpcolumn>(); } } class ClassTest { public ClassTest() { erptable table = new erptable(); table.columns = new erpcolumn[4]; table.name = "Arch"; table.noofcolumns = 4; erpcolumn col = new erpcolumn(); col.name = "Id"; col.type = 1; col.size = 4; table.columns[0] = col; table.d1["Id"] = col; erpcolumn col1 = new erpcolumn(); col1.name = "name"; col1.type = 2; col1.size = 50; table.columns[1] = col1; table.d1["name"] = col1; erpcolumn col2 = new erpcolumn(); col2.name = "no"; col2.type = 2; col2.size = 10; table.columns[2] = col2; table.d1["no"] = col2; erpcolumn col3 = new erpcolumn(); col3.name = "amount"; col3.type = 3; col3.size = 8; table.columns[3] = col3; table.d1["amount"] = col3; erpcolumn col4 = new erpcolumn(); col4.name = "sex"; col4.type = 66; col4.size = 77; table.firstcol = col4; MemoryStream ms = new MemoryStream(); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(ms, table); Console.WriteLine("Binary serialized length: {0}", ms.Length); Stream stream = File.Open("data8.xml", FileMode.Create); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, table); stream.Close(); erptable obj1 = new erptable(); stream = File.Open("data8.xml", FileMode.Open); formatter = new BinaryFormatter(); obj1 = (erptable)formatter.Deserialize(stream); stream.Close(); } }
|
|
|
|

|
I love your article and have been using your code for quite some time now for my serialization needs. I have a unique problem now though that I'm not sure how to approach with your code. I need to append objects to a file over a period of time and then later unpack all the objects. For performance and memory reasons, it's desired that I not rewrite all objects to the file every time I just write one.
Does any approach come to mind for this problem?
Thanks,
Michael
|
|
|
|

|
Thank you. Great article.
I'm astonished by the optimizations you have put in the code!
|
|
|
|

|
I have implemented IOwnedDataSerializableAndRecreatable in my Advertiser class in the hopes that I would see a marked increase in serialization/de-serialization performance as compared to using the stock .Net serialization (class has the SerializableAttribute). My first pass has left me wondering if I have done something wrong, here are my test results. I am hoping someone can shed some light on this.
Normal serialialization -- Binary serialized length: 4710 Running test for 250000 iterations done in 744.4963504 uS per cycle. 186.1
Fast serialialization -- Binary serialized length: 4715 Running test for 250000 iterations done in 778.847646 uS per cycle. 194.9
* Please note that I did NOT used the any of the optimized SimmoTech.Utils.Serialization methods during this first round of tests, but used the writer.Write(), writer.WriteObject(), reader.ReadXXX(), and reader.ReadObject().
Thank you
Stephen
[Test]
public void PefTestAdvertiser()
{
Console.WriteLine("Normal serialialization -- ");
MemoryStream ms = new MemoryStream();
new BinaryFormatter().Serialize(ms, advertiser);
Console.WriteLine("Binary serialized length: {0}", ms.Length);
ms.Position = 0;
Console.WriteLine("\nRunning test for {0} iterations", count);
DateTime t = DateTime.Now;
for (int i = 0; i < count; i++)
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, advertiser);
ms.Position = 0;
Advertiser result = (Advertiser) bf.Deserialize(ms);
}
TimeSpan ts = DateTime.Now - t;
Console.WriteLine("done in {0} uS per cycle.", ts.TotalMilliseconds * 1000.0 / count);
}
[Test]
public void PefTestFastAdvertiser()
{
Console.WriteLine("Fast serialialization -- ");
Writer.WriteObject(advertiser);
Console.WriteLine("Binary serialized length: {0}", Writer.BaseStream.Length);
Console.WriteLine("\nRunning test for {0} iterations", count);
DateTime t = DateTime.Now;
for (int i = 0; i < count; i++)
{
SerializationWriter sw = new SerializationWriter();
sw.WriteObject(advertiser);
SerializationReader sr = getReaderFromWriter(sw);
Advertiser result = (Advertiser) sr.ReadObject();
}
TimeSpan ts = DateTime.Now - t;
Console.WriteLine("done in {0} uS per cycle.", ts.TotalMilliseconds * 1000.0 / count);
}
|
|
|
|

|
Hi Stephen
If you want to post the complete code to your unit test, I don't mind having a look to see if there are optmizations to be made.
Cheers
Simon
|
|
|
|

|
I have a compressed file with everything you need, please email me at stephenpatten AT gmail and I will send it to you.
|
|
|
|

|
Simon,
Thanks for working with me on this! My results have swung 180 or more if that's possible... I am now serializing/deserializing my custom objects in 1/10,000 of the time... I knew it was going to be fast, but not this fast. That lead me to believe that something was wrong so I went digging and found that only the base class was being converted not the derived classes...wonder what's up?
Stephen
|
|
|
|

|
Hi Simon, I was testing a simple scenario - a root object that contains a generic list and 100,000 such (root) objects to be serialized separately. This was to compare the average serialization time between the (1) default serialization, (2) custom (SerializationInfo.AddValue for each attribute) and (3) your approach. I was expecting that your approach would be faster, but I found the results quite surprising. The FastSerializer is slower than even the default approach (10 seconds vs 4.5 for default and 3.5 for custom - for the 100,000 objects). Am I doing something wrong here? Please see code below.
sw.WriteOptimized(_name);
sw.WriteOptimized(_email);
sw.WriteObject(_addr);
sw.Write<Address>(_addrs);
info.AddValue("data", sw.ToArray());
|
|
|
|

|
If you want to post a sample project here with test data, I don't mind having a look.
Off the top of my head, it is the collection that should be considered the root and 'own's all of its child objects and 'knows' how to write their contents into a single serialization writer. If you are letting each of the 100,000 use their own serialization writer (or are using a single writer but calling ToArray on it 100,000 times) then it would indeed be slower I suspect.
Cheers
Simon
Cheers
Simon
|
|
|
|

|
Hi Simon, Thanx for the reply. The reason I was running the scenario 100,000 times was to get an average time for the serialization process. Another test I did was to have a list with 1000 items and ran the serialization process for 1000 times. The results were not encouraging either. So I was wondering if I was doing something wrong in my code. As I said before, the scenario is simple and I was trying to find a more optimized way of serializing. Anyway, I will profile the code and see where exactly it is slow and possibly post the code for your review. Once again, thanx for replying.
Regards,
Raghu
|
|
|
|

|
Funny, I just came to the same conclusion...well, really it's not that funny, serialization is killing me right now
Regards,
Stephen
|
|
|
|

|
Simon,
Have you any update related to processing entities, it seems that's the only model I work with as of late.
BTW, Thank you for the very thorough unit tests!
Regards,
Stephen
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
Provides code and techniques to enable developers to optimize serialization of data
| Type | Article |
| Licence | Public Domain |
| First Posted | 24 Sep 2006 |
| Views | 267,433 |
| Downloads | 2,994 |
| Bookmarked | 314 times |
|
|