diff --git a/Implab/JSON/JSONWriter.cs b/Implab/JSON/JSONWriter.cs --- a/Implab/JSON/JSONWriter.cs +++ b/Implab/JSON/JSONWriter.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Globalization; +using System.Diagnostics; namespace Implab.JSON { public class JSONWriter { @@ -12,10 +13,15 @@ namespace Implab.JSON { Stack m_contextStack = new Stack(); Context m_context; + const int BUFFER_SIZE = 64; + TextWriter m_writer; readonly bool m_indent = true; readonly int m_indentSize = 4; + readonly char[] m_buffer = new char[BUFFER_SIZE]; + int m_bufferPos; + static readonly char [] _hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; static readonly char [] _escapeBKS, _escapeFWD, _escapeCR, @@ -211,7 +217,13 @@ namespace Implab.JSON { void Write(bool value) { m_writer.Write(value ? "true" : "false"); } - + + void FlushBuffer() { + if (m_bufferPos > 0) { + m_writer.Write(m_buffer, 0, m_bufferPos); + m_bufferPos = 0; + } + } void Write(string value) { if (value == null) { @@ -219,46 +231,73 @@ namespace Implab.JSON { return; } + Debug.Assert(m_bufferPos == 0); + var chars = value.ToCharArray(); - m_writer.Write('"'); - + m_buffer[m_bufferPos++] = '"'; + // Analysis disable once ForCanBeConvertedToForeach for (int i = 0; i < chars.Length; i++) { var ch = chars[i]; + char[] escapeSeq; + switch (ch) { case '\b': - m_writer.Write(_escapeBKS); + escapeSeq = _escapeBKS; break; case '\f': - m_writer.Write(_escapeFWD); + escapeSeq = _escapeFWD; break; case '\r': - m_writer.Write(_escapeCR); + escapeSeq = _escapeCR; break; case '\n': - m_writer.Write(_escapeNL); + escapeSeq = _escapeNL; break; case '\t': - m_writer.Write(_escapeTAB); + escapeSeq = _escapeTAB; break; case '\\': - m_writer.Write(_escapeBSLASH); + escapeSeq = _escapeBSLASH; break; case '"': - m_writer.Write(_escapeQ); + escapeSeq = _escapeQ; break; default: if (ch < 0x20) { - m_writer.Write("\\u00{0:x2}",(int)ch); + if (m_bufferPos + 6 > BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '\\'; + m_buffer[m_bufferPos++] = 'u'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = '0'; + m_buffer[m_bufferPos++] = _hex[ch >> 4 & 0xf]; + m_buffer[m_bufferPos++] = _hex[ch & 0xf]; + } else { - m_writer.Write(ch); + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + m_buffer[m_bufferPos++] = ch; } - break; + continue; } + + if (m_bufferPos + escapeSeq.Length > BUFFER_SIZE) + FlushBuffer(); + + Array.Copy(escapeSeq, 0, m_buffer, m_bufferPos, escapeSeq.Length); + m_bufferPos += escapeSeq.Length; + } - m_writer.Write('"'); + if (m_bufferPos >= BUFFER_SIZE) + FlushBuffer(); + + m_buffer[m_bufferPos++] = '"'; + + FlushBuffer(); } void Write(double value) { diff --git a/MonoPlay/Program.cs b/MonoPlay/Program.cs --- a/MonoPlay/Program.cs +++ b/MonoPlay/Program.cs @@ -5,6 +5,8 @@ using Implab; using System.Collections.Generic; using System.Collections.Concurrent; using System.Threading; +using Implab.JSON; +using System.IO; namespace MonoPlay { class MainClass { @@ -16,25 +18,27 @@ namespace MonoPlay { var t1 = Environment.TickCount; - for (int i = 0; i < 10000000; i++) { - - var p = new Promise(); - p.On(HandleResult); - p.Resolve(i); + for(int i =0; i < 1000000; i++) + using (var tw = new StringWriter()) { + var jw = new JSONWriter(tw); + + jw.WriteValue("\r\nhere\tvalue\u0002\u0003"); + + //Console.WriteLine(tw); } + + var t2 = Environment.TickCount; Console.WriteLine("done: {0} ms, {1:.00} Mb, {2} GC", t2 - t1, GC.GetTotalMemory(false) / (1024*1024), GC.CollectionCount(0) ); } - static void HandleAction () - { - + static void DoTest() { + + + } - static void HandleResult(int x) { - - } } }