Figure
1 .NET Value Types
System Type |
C# Type |
Managed Size in Bytes |
Default Unmanaged Size in Bytes |
System.Boolean |
bool |
1 |
4 |
System.Byte |
byte |
1 |
1 |
System.Char |
char |
2 |
1 |
System.Decimal |
decimal |
16 |
16 |
System.Double |
double |
8 |
8 |
System.Single |
float |
4 |
4 |
System.Int16 |
short |
2 |
2 |
System.Int32 |
int |
4 |
4 |
System.Int64 |
long |
8 |
8 |
System.SByte |
sbyte |
1 |
1 |
System.UInt16 |
ushort |
2 |
2 |
System.UInt32 |
uint |
4 |
4 |
System.UInt64 |
ulong |
8 |
8 |
Figure 2 AddressType
enum AddressType
{
Home,
Secondary,
Office
}
class Address
{
public bool IsPayTo;
public AddressType
AddressType;
public string Address1;
public string Address2;
public string City;
public string State;
public string Zip;
}
Figure 3 Reducing
Type Size
enum AddressType : short
{
Home,
Secondary,
Office
}
class Address
{
byte _isPayTo;
AddressType _addrType;
string _address1;
string _address2;
string _city;
string _state;
string _zip;
public bool IsPayTo
{
get { return (_isPayTo == 1); }
set { _isPayTo = (byte)(value ? 1 : 0); }
}
public string State
{
get { return _state; }
set
{
if (value == null) _state = null;
else _state = String.Intern(value.ToUpper());
}
}
public AddressType AddressType
{
get { return _addrType; } set { _addrType = value; }
}
public string Address1
{
get { return _address1; } set { _address1 = value; }
}
public string Address2
{
get { return _address2; } set { _address2 = value; }
}
public string City { ... }
public string Zip { ... }
}
Figure 4 ObjectPool
in .NET
public class ObjectPool
{
// ObjectPool is implemented as a Singleton
public static ObjectPool GetInstance() { ... }
// Delegates used by the interface
public delegate object CreateObject();
public delegate void UseObject(object obj, object [] args);
// Initiate pooling for the given type
public void RegisterType(Type t, CreateObject createDelegate,
short minPoolSize, short maxPoolSize, int creationTimeout) { ... }
// Terminate pooling for the given type
public void UnregisterType(Type t) { ... }
// Get and release objects in the pool
public object GetObject(Type t) { ... }
public void ReleaseObject(object obj) { ... }
// Execute the given method using an object from the pool
public void ExecuteFromPool(Type t,
UseObject executeDelegate, object [] args) { ... }
}
Figure 5 ReleaseObject
Method
private void ReturnToPool(object obj, ObjectData data)
{
Monitor.Enter(data);
try
{
data.inUse—;
int size = data.inUse + data.inPool;
if (size < data.minPoolSize)
{
// Return actual object to the pool
data.pool.Enqueue(obj);
data.inPool++;
}
else
{
// Min available, so enqueue weak reference
WeakReference weakRef = new WeakReference(obj);
data.pool.Enqueue(weakRef);
}
// Notify waiting threads
if (data.inWait > 0) Monitor.Pulse(data);
}
finally { Monitor.Exit(data); }
}
Figure 6 RetrieveFromPool
Method
private object AllocateObject(ObjectData data)
{
return data.createDelegate();
}
private object DequeueFromPool(ObjectData data)
{
object result;
do
{
// This presumes pool is non-empty
result = data.pool.Dequeue();
if (result is WeakReference)
result = ((WeakReference)result).Target;
else
data.inPool—;
} while (result == null && data.pool.Count > 0);
return result;
}
private object RetrieveFromPool(ObjectData data)
{
object result = null;
int waitTime = (data.creationTimeout > 0) ?
data.creationTimeout : Timeout.Infinite;
try
{
// Try to obtain lock
int startTick = Environment.TickCount;
if (Monitor.TryEnter(data, waitTime) == false) return null;
if (data.pool.Count > 0) result = DequeueFromPool(data);
if (result == null)
{
// Pool empty or all weak refs
if (data.maxPoolSize == 0 || data.inUse < data.maxPoolSize)
result = AllocateObject(data);
else
{
if (waitTime != Timeout.Infinite)
waitTime -= (Environment.TickCount - startTick);
result = WaitForObject(data, waitTime);
}
}
// Update inUse counter.
if (result != null) data.inUse++;
}
finally { Monitor.Exit(data); }
return result;
}
Figure 7 ExecuteFromPool
Method
private ObjectData GetObjectData(Type t)
{
// The private ObjectData class holds stats for each type.
ObjectData data = Table[t.FullName] as ObjectData;
if (data == null) throw new ArgumentException(...);
return data;
}
public void ExecuteFromPool(Type t,
UseObject executeDelegate, object [] args)
{
ObjectData data = GetObjectData(t);
object obj = null;
try
{
// Retrieve an object from the pool
obj = RetrieveFromPool(data);
if (obj == null) throw new ObjectPoolException(...);
// Execute given delegate with pooled object
executeDelegate(obj, args);
}
finally
{
// Return retrieved object to pool
if (obj != null) ReturnToPool(obj, data);
}
}
Figure 8 File
Streaming
static void ProcessFile(FileStream fin, FileStream fout)
{
int next;
while ((next = fin.ReadByte()) != -1)
{
byte b = (byte)next;
if (b == 'n' || b == 'N')
CheckForWordAndWrite(fin, fout, "nation", "country", b);
else if (b == 'l' || b == 'L')
CheckForWordAndWrite(fin, fout, "liberty", "freedom", b);
else
fout.WriteByte(b);
}
}
static void CheckForWordAndWrite(Stream si, Stream so,
string word, string replace, byte first)
{
int len = word.Length;
long pos = si.Position;
byte[] buf = new byte[len];
buf[0] = first;
si.Read(buf, 1, word.Length-1);
string data = Encoding.ASCII.GetString(buf);
if (String.Compare(word, data, true) == 0)
so.Write(Encoding.ASCII.GetBytes(replace), 0, replace.Length);
else
{
si.Position = pos; // reset stream
so.WriteByte(first); // write orig byte
}
}