[Mono.Profiler.Log] Load entire buffers before processing them.
authorAlex Rønne Petersen <alpeters@microsoft.com>
Wed, 20 Sep 2017 12:32:07 +0000 (14:32 +0200)
committerAlex Rønne Petersen <alpeters@microsoft.com>
Wed, 20 Sep 2017 12:32:07 +0000 (14:32 +0200)
This should reduce the amount of I/O system calls we do, and should be fine
in terms of memory usage since the profiler tries to keep buffers small (64k),
and latency since the profiler flushes buffers every second.

This changes the API somewhat so that users no longer have to construct a
LogReader; this is now done internally, and the type is no longer public. Also,
the LogProcessor now leaves the given stream open, so it's up to the user to
close it.

mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogProcessor.cs
mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogReader.cs

index 71bdca3f0dc1defe85366f1b7ba93cc4c373a101..7e9871efa63034dda37fcfb542604b4b393d9a63 100644 (file)
@@ -12,7 +12,7 @@ namespace Mono.Profiler.Log {
 
        public sealed class LogProcessor {
 
-               public LogReader Reader { get; }
+               public LogStream Stream { get; }
 
                public LogEventVisitor ImmediateVisitor { get; }
 
@@ -20,18 +20,20 @@ namespace Mono.Profiler.Log {
 
                public LogStreamHeader StreamHeader { get; private set; }
 
+               LogReader _reader;
+
                LogBufferHeader _bufferHeader;
 
                ulong _time;
 
                bool _used;
 
-               public LogProcessor (LogReader reader, LogEventVisitor immediateVisitor, LogEventVisitor sortedVisitor)
+               public LogProcessor (LogStream stream, LogEventVisitor immediateVisitor, LogEventVisitor sortedVisitor)
                {
-                       if (reader == null)
-                               throw new ArgumentNullException (nameof (reader));
+                       if (stream == null)
+                               throw new ArgumentNullException (nameof (stream));
 
-                       Reader = reader;
+                       Stream = stream;
                        ImmediateVisitor = immediateVisitor;
                        SortedVisitor = sortedVisitor;
                }
@@ -66,29 +68,44 @@ namespace Mono.Profiler.Log {
                                throw new InvalidOperationException ("This log processor cannot be reused.");
 
                        _used = true;
-                       StreamHeader = new LogStreamHeader (Reader);
+                       _reader = new LogReader (Stream, true);
+
+                       StreamHeader = new LogStreamHeader (_reader);
 
                        var events = new List<LogEvent> (Environment.ProcessorCount * 1000);
 
-                       while (!Reader.BaseStream.EndOfStream) {
+                       while (!Stream.EndOfStream) {
                                token.ThrowIfCancellationRequested ();
 
-                               _bufferHeader = new LogBufferHeader (StreamHeader, Reader);
+                               _bufferHeader = new LogBufferHeader (StreamHeader, _reader);
+
+                               // Read the entire buffer into a MemoryStream ahead of time to
+                               // reduce the amount of I/O system calls we do. This should be
+                               // fine since the profiler tries to keep buffers small and
+                               // flushes them every second at minimum. This also has the
+                               // advantage that we can use the Position and Length properties
+                               // even if the stream we read the buffer from is actually
+                               // non-seekable.
+                               var stream = new MemoryStream (_reader.ReadBytes (_bufferHeader.Length), false);
 
-                               // Use the manual position tracking in LogReader so we're
-                               // compatible with non-seekable streams.
-                               var goal = Reader.Position + _bufferHeader.Length;
+                               using (var reader = new LogReader (stream, false)) {
+                                       var oldReader = _reader;
 
-                               while (Reader.Position < goal) {
-                                       token.ThrowIfCancellationRequested ();
+                                       _reader = reader;
 
-                                       var ev = ReadEvent ();
+                                       while (stream.Position < stream.Length) {
+                                               token.ThrowIfCancellationRequested ();
 
-                                       ProcessEvent (ImmediateVisitor, ev);
-                                       events.Add (ev);
+                                               var ev = ReadEvent ();
+
+                                               ProcessEvent (ImmediateVisitor, ev);
+                                               events.Add (ev);
+
+                                               if (ev is SynchronizationPointEvent)
+                                                       ProcessEvents (events, token);
+                                       }
 
-                                       if (ev is SynchronizationPointEvent)
-                                               ProcessEvents (events, token);
+                                       _reader = oldReader;
                                }
                        }
 
@@ -97,7 +114,7 @@ namespace Mono.Profiler.Log {
 
                LogEvent ReadEvent ()
                {
-                       var type = Reader.ReadByte ();
+                       var type = _reader.ReadByte ();
                        var basicType = (LogEventType) (type & 0xf);
                        var extType = (LogEventType) (type & 0xf0);
 
@@ -112,7 +129,7 @@ namespace Mono.Profiler.Log {
                                        ev = new AllocationEvent {
                                                ClassPointer = ReadPointer (),
                                                ObjectPointer = ReadObject (),
-                                               ObjectSize = (long) Reader.ReadULeb128 (),
+                                               ObjectSize = (long) _reader.ReadULeb128 (),
                                                Backtrace = ReadBacktrace (extType == LogEventType.AllocationBacktrace),
                                        };
                                        break;
@@ -124,17 +141,17 @@ namespace Mono.Profiler.Log {
                                switch (extType) {
                                case LogEventType.GCEvent:
                                        ev = new GCEvent {
-                                               Type = (LogGCEvent) Reader.ReadByte (),
-                                               Generation = Reader.ReadByte (),
+                                               Type = (LogGCEvent) _reader.ReadByte (),
+                                               Generation = _reader.ReadByte (),
                                        };
                                        break;
                                case LogEventType.GCResize:
                                        ev = new GCResizeEvent {
-                                               NewSize = (long) Reader.ReadULeb128 (),
+                                               NewSize = (long) _reader.ReadULeb128 (),
                                        };
                                        break;
                                case LogEventType.GCMove: {
-                                       var list = new long [(int) Reader.ReadULeb128 ()];
+                                       var list = new long [(int) _reader.ReadULeb128 ()];
 
                                        for (var i = 0; i < list.Length; i++)
                                                list [i] = ReadObject ();
@@ -148,8 +165,8 @@ namespace Mono.Profiler.Log {
                                case LogEventType.GCHandleCreationNoBacktrace:
                                case LogEventType.GCHandleCreationBacktrace:
                                        ev = new GCHandleCreationEvent {
-                                               Type = (LogGCHandleType) Reader.ReadULeb128 (),
-                                               Handle = (long) Reader.ReadULeb128 (),
+                                               Type = (LogGCHandleType) _reader.ReadULeb128 (),
+                                               Handle = (long) _reader.ReadULeb128 (),
                                                ObjectPointer = ReadObject (),
                                                Backtrace = ReadBacktrace (extType == LogEventType.GCHandleCreationBacktrace),
                                        };
@@ -157,8 +174,8 @@ namespace Mono.Profiler.Log {
                                case LogEventType.GCHandleDeletionNoBacktrace:
                                case LogEventType.GCHandleDeletionBacktrace:
                                        ev = new GCHandleDeletionEvent {
-                                               Type = (LogGCHandleType) Reader.ReadULeb128 (),
-                                               Handle = (long) Reader.ReadULeb128 (),
+                                               Type = (LogGCHandleType) _reader.ReadULeb128 (),
+                                               Handle = (long) _reader.ReadULeb128 (),
                                                Backtrace = ReadBacktrace (extType == LogEventType.GCHandleDeletionBacktrace),
                                        };
                                        break;
@@ -199,7 +216,7 @@ namespace Mono.Profiler.Log {
                                        throw new LogException ($"Invalid extended event type ({extType}).");
                                }
 
-                               var metadataType = (LogMetadataType) Reader.ReadByte ();
+                               var metadataType = (LogMetadataType) _reader.ReadByte ();
 
                                switch (metadataType) {
                                case LogMetadataType.Class:
@@ -207,7 +224,7 @@ namespace Mono.Profiler.Log {
                                                ev = new ClassLoadEvent {
                                                        ClassPointer = ReadPointer (),
                                                        ImagePointer = ReadPointer (),
-                                                       Name = Reader.ReadCString (),
+                                                       Name = _reader.ReadCString (),
                                                };
                                        } else
                                                throw new LogException ("Invalid class metadata event.");
@@ -216,12 +233,12 @@ namespace Mono.Profiler.Log {
                                        if (load) {
                                                ev = new ImageLoadEvent {
                                                        ImagePointer = ReadPointer (),
-                                                       Name = Reader.ReadCString (),
+                                                       Name = _reader.ReadCString (),
                                                };
                                        } else if (unload) {
                                                ev = new ImageUnloadEvent {
                                                        ImagePointer = ReadPointer (),
-                                                       Name = Reader.ReadCString (),
+                                                       Name = _reader.ReadCString (),
                                                };
                                        } else
                                                throw new LogException ("Invalid image metadata event.");
@@ -231,13 +248,13 @@ namespace Mono.Profiler.Log {
                                                ev = new AssemblyLoadEvent {
                                                        AssemblyPointer = ReadPointer (),
                                                        ImagePointer = StreamHeader.FormatVersion >= 14 ? ReadPointer () : 0,
-                                                       Name = Reader.ReadCString (),
+                                                       Name = _reader.ReadCString (),
                                                };
                                        } else if (unload) {
                                                ev = new AssemblyUnloadEvent {
                                                        AssemblyPointer = ReadPointer (),
                                                        ImagePointer = StreamHeader.FormatVersion >= 14 ? ReadPointer () : 0,
-                                                       Name = Reader.ReadCString (),
+                                                       Name = _reader.ReadCString (),
                                                };
                                        } else
                                                throw new LogException ("Invalid assembly metadata event.");
@@ -254,7 +271,7 @@ namespace Mono.Profiler.Log {
                                        } else {
                                                ev = new AppDomainNameEvent {
                                                        AppDomainId = ReadPointer (),
-                                                       Name = Reader.ReadCString (),
+                                                       Name = _reader.ReadCString (),
                                                };
                                        }
                                        break;
@@ -270,7 +287,7 @@ namespace Mono.Profiler.Log {
                                        } else {
                                                ev = new ThreadNameEvent {
                                                        ThreadId = ReadPointer (),
-                                                       Name = Reader.ReadCString (),
+                                                       Name = _reader.ReadCString (),
                                                };
                                        }
                                        break;
@@ -314,8 +331,8 @@ namespace Mono.Profiler.Log {
                                        ev = new JitEvent {
                                                MethodPointer = ReadMethod (),
                                                CodePointer = ReadPointer (),
-                                               CodeSize = (long) Reader.ReadULeb128 (),
-                                               Name = Reader.ReadCString (),
+                                               CodeSize = (long) _reader.ReadULeb128 (),
+                                               Name = _reader.ReadCString (),
                                        };
                                        break;
                                default:
@@ -333,8 +350,8 @@ namespace Mono.Profiler.Log {
                                        break;
                                case LogEventType.ExceptionClause:
                                        ev = new ExceptionClauseEvent {
-                                               Type = (LogExceptionClause) Reader.ReadByte (),
-                                               Index = (long) Reader.ReadULeb128 (),
+                                               Type = (LogExceptionClause) _reader.ReadByte (),
+                                               Index = (long) _reader.ReadULeb128 (),
                                                MethodPointer = ReadMethod (),
                                                ObjectPointer = StreamHeader.FormatVersion >= 14 ? ReadObject () : 0,
                                        };
@@ -356,7 +373,7 @@ namespace Mono.Profiler.Log {
                                case LogEventType.MonitorBacktrace:
                                        ev = new MonitorEvent {
                                                Event = StreamHeader.FormatVersion >= 14 ?
-                                                                   (LogMonitorEvent) Reader.ReadByte () :
+                                                                   (LogMonitorEvent) _reader.ReadByte () :
                                                                    (LogMonitorEvent) ((((byte) type & 0xf0) >> 4) & 0x3),
                                                ObjectPointer = ReadObject (),
                                                Backtrace = ReadBacktrace (extType == LogEventType.MonitorBacktrace),
@@ -378,14 +395,14 @@ namespace Mono.Profiler.Log {
                                        HeapObjectEvent hoe = new HeapObjectEvent {
                                                ObjectPointer = ReadObject (),
                                                ClassPointer = ReadPointer (),
-                                               ObjectSize = (long) Reader.ReadULeb128 (),
+                                               ObjectSize = (long) _reader.ReadULeb128 (),
                                        };
 
-                                       var list = new HeapObjectEvent.HeapObjectReference [(int) Reader.ReadULeb128 ()];
+                                       var list = new HeapObjectEvent.HeapObjectReference [(int) _reader.ReadULeb128 ()];
 
                                        for (var i = 0; i < list.Length; i++) {
                                                list [i] = new HeapObjectEvent.HeapObjectReference {
-                                                       Offset = (long) Reader.ReadULeb128 (),
+                                                       Offset = (long) _reader.ReadULeb128 (),
                                                        ObjectPointer = ReadObject (),
                                                };
                                        }
@@ -399,15 +416,15 @@ namespace Mono.Profiler.Log {
                                case LogEventType.HeapRoots: {
                                        // TODO: This entire event makes no sense.
                                        var hre = new HeapRootsEvent ();
-                                       var list = new HeapRootsEvent.HeapRoot [(int) Reader.ReadULeb128 ()];
+                                       var list = new HeapRootsEvent.HeapRoot [(int) _reader.ReadULeb128 ()];
 
-                                       hre.MaxGenerationCollectionCount = (long) Reader.ReadULeb128 ();
+                                       hre.MaxGenerationCollectionCount = (long) _reader.ReadULeb128 ();
 
                                        for (var i = 0; i < list.Length; i++) {
                                                list [i] = new HeapRootsEvent.HeapRoot {
                                                        ObjectPointer = ReadObject (),
-                                                       Attributes = StreamHeader.FormatVersion == 13 ? (LogHeapRootAttributes) Reader.ReadByte () : (LogHeapRootAttributes) Reader.ReadULeb128 (),
-                                                       ExtraInfo = (long) Reader.ReadULeb128 (),
+                                                       Attributes = StreamHeader.FormatVersion == 13 ? (LogHeapRootAttributes) _reader.ReadByte () : (LogHeapRootAttributes) _reader.ReadULeb128 (),
+                                                       ExtraInfo = (long) _reader.ReadULeb128 (),
                                                };
                                        }
 
@@ -425,7 +442,7 @@ namespace Mono.Profiler.Log {
                                case LogEventType.SampleHit:
                                        if (StreamHeader.FormatVersion < 14) {
                                                // Read SampleType (always set to .Cycles) for versions < 14
-                                               Reader.ReadByte ();
+                                               _reader.ReadByte ();
                                        }
                                        ev = new SampleHitEvent {
                                                ThreadId = ReadPointer (),
@@ -436,33 +453,33 @@ namespace Mono.Profiler.Log {
                                case LogEventType.SampleUnmanagedSymbol:
                                        ev = new UnmanagedSymbolEvent {
                                                CodePointer = ReadPointer (),
-                                               CodeSize = (long) Reader.ReadULeb128 (),
-                                               Name = Reader.ReadCString (),
+                                               CodeSize = (long) _reader.ReadULeb128 (),
+                                               Name = _reader.ReadCString (),
                                        };
                                        break;
                                case LogEventType.SampleUnmanagedBinary:
                                        ev = new UnmanagedBinaryEvent {
-                                               SegmentPointer = StreamHeader.FormatVersion >= 14 ? ReadPointer () : Reader.ReadSLeb128 (),
-                                               SegmentOffset = (long) Reader.ReadULeb128 (),
-                                               SegmentSize = (long) Reader.ReadULeb128 (),
-                                               FileName = Reader.ReadCString (),
+                                               SegmentPointer = StreamHeader.FormatVersion >= 14 ? ReadPointer () : _reader.ReadSLeb128 (),
+                                               SegmentOffset = (long) _reader.ReadULeb128 (),
+                                               SegmentSize = (long) _reader.ReadULeb128 (),
+                                               FileName = _reader.ReadCString (),
                                        };
                                        break;
                                case LogEventType.SampleCounterDescriptions: {
                                        var cde = new CounterDescriptionsEvent ();
-                                       var list = new CounterDescriptionsEvent.CounterDescription [(int) Reader.ReadULeb128 ()];
+                                       var list = new CounterDescriptionsEvent.CounterDescription [(int) _reader.ReadULeb128 ()];
 
                                        for (var i = 0; i < list.Length; i++) {
-                                               var section = (LogCounterSection) Reader.ReadULeb128 ();
+                                               var section = (LogCounterSection) _reader.ReadULeb128 ();
 
                                                list [i] = new CounterDescriptionsEvent.CounterDescription {
                                                        Section = section,
-                                                       SectionName = section == LogCounterSection.User ? Reader.ReadCString () : string.Empty,
-                                                       CounterName = Reader.ReadCString (),
-                                                       Type = (LogCounterType) Reader.ReadByte (),
-                                                       Unit = (LogCounterUnit) Reader.ReadByte (),
-                                                       Variance = (LogCounterVariance) Reader.ReadByte (),
-                                                       Index = (long) Reader.ReadULeb128 (),
+                                                       SectionName = section == LogCounterSection.User ? _reader.ReadCString () : string.Empty,
+                                                       CounterName = _reader.ReadCString (),
+                                                       Type = (LogCounterType) _reader.ReadByte (),
+                                                       Unit = (LogCounterUnit) _reader.ReadByte (),
+                                                       Variance = (LogCounterVariance) _reader.ReadByte (),
+                                                       Index = (long) _reader.ReadULeb128 (),
                                                };
                                        }
 
@@ -476,31 +493,31 @@ namespace Mono.Profiler.Log {
                                        var list = new List<CounterSamplesEvent.CounterSample> ();
 
                                        while (true) {
-                                               var index = (long) Reader.ReadULeb128 ();
+                                               var index = (long) _reader.ReadULeb128 ();
 
                                                if (index == 0)
                                                        break;
 
-                                               var counterType = (LogCounterType) Reader.ReadByte ();
+                                               var counterType = (LogCounterType) _reader.ReadByte ();
 
                                                object value = null;
 
                                                switch (counterType) {
                                                case LogCounterType.String:
-                                                       value = Reader.ReadByte () == 1 ? Reader.ReadCString () : null;
+                                                       value = _reader.ReadByte () == 1 ? _reader.ReadCString () : null;
                                                        break;
                                                case LogCounterType.Int32:
                                                case LogCounterType.Word:
                                                case LogCounterType.Int64:
                                                case LogCounterType.Interval:
-                                                       value = Reader.ReadSLeb128 ();
+                                                       value = _reader.ReadSLeb128 ();
                                                        break;
                                                case LogCounterType.UInt32:
                                                case LogCounterType.UInt64:
-                                                       value = Reader.ReadULeb128 ();
+                                                       value = _reader.ReadULeb128 ();
                                                        break;
                                                case LogCounterType.Double:
-                                                       value = Reader.ReadDouble ();
+                                                       value = _reader.ReadDouble ();
                                                        break;
                                                default:
                                                        throw new LogException ($"Invalid counter type ({counterType}).");
@@ -525,13 +542,13 @@ namespace Mono.Profiler.Log {
                        case LogEventType.Runtime:
                                switch (extType) {
                                case LogEventType.RuntimeJitHelper: {
-                                       var helperType = (LogJitHelper) Reader.ReadByte ();
+                                       var helperType = (LogJitHelper) _reader.ReadByte ();
 
                                        ev = new JitHelperEvent {
                                                Type = helperType,
                                                BufferPointer = ReadPointer (),
-                                               BufferSize = (long) Reader.ReadULeb128 (),
-                                               Name = helperType == LogJitHelper.SpecificTrampoline ? Reader.ReadCString () : string.Empty,
+                                               BufferSize = (long) _reader.ReadULeb128 (),
+                                               Name = helperType == LogJitHelper.SpecificTrampoline ? _reader.ReadCString () : string.Empty,
                                        };
                                        break;
                                }
@@ -543,7 +560,7 @@ namespace Mono.Profiler.Log {
                                switch (extType) {
                                case LogEventType.MetaSynchronizationPoint:
                                        ev = new SynchronizationPointEvent {
-                                               Type = (LogSynchronizationPoint) Reader.ReadByte (),
+                                               Type = (LogSynchronizationPoint) _reader.ReadByte (),
                                        };
                                        break;
                                default:
@@ -562,24 +579,24 @@ namespace Mono.Profiler.Log {
 
                long ReadPointer ()
                {
-                       var ptr = Reader.ReadSLeb128 () + _bufferHeader.PointerBase;
+                       var ptr = _reader.ReadSLeb128 () + _bufferHeader.PointerBase;
 
                        return StreamHeader.PointerSize == sizeof (long) ? ptr : ptr & 0xffffffffL;
                }
 
                long ReadObject ()
                {
-                       return Reader.ReadSLeb128 () + _bufferHeader.ObjectBase << 3;
+                       return _reader.ReadSLeb128 () + _bufferHeader.ObjectBase << 3;
                }
 
                long ReadMethod ()
                {
-                       return _bufferHeader.CurrentMethod += Reader.ReadSLeb128 ();
+                       return _bufferHeader.CurrentMethod += _reader.ReadSLeb128 ();
                }
 
                ulong ReadTime ()
                {
-                       return _bufferHeader.CurrentTime += Reader.ReadULeb128 ();
+                       return _bufferHeader.CurrentTime += _reader.ReadULeb128 ();
                }
 
                IReadOnlyList<long> ReadBacktrace (bool actuallyRead, bool managed = true)
@@ -587,7 +604,7 @@ namespace Mono.Profiler.Log {
                        if (!actuallyRead)
                                return Array.Empty<long> ();
 
-                       var list = new long [(int) Reader.ReadULeb128 ()];
+                       var list = new long [(int) _reader.ReadULeb128 ()];
 
                        for (var i = 0; i < list.Length; i++)
                                list [i] = managed ? ReadMethod () : ReadPointer ();
index 4b241ba155d11db44c5850a67b56d7438057bf09..a58211a1510642ca2a0d8eaa9eabc507598f490b 100644 (file)
@@ -3,27 +3,22 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
-using System.Collections.Generic;
 using System.IO;
 using System.Text;
 
 namespace Mono.Profiler.Log {
 
-       public sealed class LogReader : IDisposable {
+       sealed class LogReader : IDisposable {
 
-               public static Encoding Encoding { get; } = Encoding.UTF8;
-
-               public LogStream BaseStream => (LogStream) _reader.BaseStream;
-
-               public long Position { get; private set; }
+               static readonly Encoding _encoding = Encoding.UTF8;
 
                readonly BinaryReader _reader;
 
                byte[] _stringBuffer = new byte [1024];
 
-               public LogReader (LogStream stream, bool leaveOpen)
+               public LogReader (Stream stream, bool leaveOpen)
                {
-                       _reader = new BinaryReader (stream, Encoding, leaveOpen);
+                       _reader = new BinaryReader (stream, _encoding, leaveOpen);
                }
 
                public void Dispose ()
@@ -31,73 +26,54 @@ namespace Mono.Profiler.Log {
                        _reader.Dispose ();
                }
 
-               internal byte ReadByte ()
+               public byte[] ReadBytes (int count)
                {
-                       var b = _reader.ReadByte ();
+                       var bytes = new byte [count];
 
-                       Position += sizeof (byte);
+                       // BinaryReader.ReadBytes doesn't necessarily read the specified
+                       // amount of bytes, so just do it this way.
+                       for (var i = 0; i < bytes.Length; i++)
+                               bytes [i] = ReadByte ();
 
-                       return b;
+                       return bytes;
                }
 
-               internal ushort ReadUInt16 ()
+               public byte ReadByte ()
                {
-                       var i = _reader.ReadUInt16 ();
-
-                       Position += sizeof (ushort);
-
-                       return i;
+                       return _reader.ReadByte ();
                }
 
-               internal int ReadInt32 ()
+               public ushort ReadUInt16 ()
                {
-                       var i = _reader.ReadInt32 ();
-
-                       Position += sizeof (int);
-
-                       return i;
+                       return _reader.ReadUInt16 ();
                }
 
-               internal long ReadInt64 ()
+               public int ReadInt32 ()
                {
-                       var i = _reader.ReadInt64 ();
-
-                       Position += sizeof (long);
-
-                       return i;
+                       return _reader.ReadInt32 ();
                }
 
-               internal ulong ReadUInt64 ()
+               public long ReadInt64 ()
                {
-                       var i = _reader.ReadUInt64 ();
-
-                       Position += sizeof (ulong);
-
-                       return i;
+                       return _reader.ReadInt64 ();
                }
 
-               internal double ReadDouble ()
+               public ulong ReadUInt64 ()
                {
-                       var d = _reader.ReadDouble ();
-
-                       Position += sizeof (double);
-
-                       return d;
+                       return _reader.ReadUInt64 ();
                }
 
-               internal string ReadHeaderString ()
+               public double ReadDouble ()
                {
-                       var bytes = new byte [ReadInt32 ()];
-
-                       // ReadBytes doesn't necessarily read the specified amount of
-                       // bytes, so just do it this way.
-                       for (var i = 0; i < bytes.Length; i++)
-                               bytes [i] = ReadByte ();
+                       return _reader.ReadDouble ();
+               }
 
-                       return Encoding.GetString (bytes);
+               public string ReadHeaderString ()
+               {
+                       return _encoding.GetString (ReadBytes (ReadInt32 ()));
                }
 
-               internal string ReadCString ()
+               public string ReadCString ()
                {
                        var pos = 0;
 
@@ -110,10 +86,10 @@ namespace Mono.Profiler.Log {
                                _stringBuffer [pos++] = val;
                        }
 
-                       return Encoding.GetString (_stringBuffer, 0, pos);
+                       return _encoding.GetString (_stringBuffer, 0, pos);
                }
 
-               internal long ReadSLeb128 ()
+               public long ReadSLeb128 ()
                {
                        long result = 0;
                        var shift = 0;
@@ -135,7 +111,7 @@ namespace Mono.Profiler.Log {
                        return result;
                }
 
-               internal ulong ReadULeb128 ()
+               public ulong ReadULeb128 ()
                {
                        ulong result = 0;
                        var shift = 0;