From 0e0113ef0e6a58889d5d47822e6d7bc3bd5993eb Mon Sep 17 00:00:00 2001 From: Ferdinand Majerech Date: Sat, 29 Oct 2011 18:21:44 +0200 Subject: [PATCH] Moved variant.d to dyaml/std/variant. Profile build doesn't inline anymore (made profiling too difficult). More optimizations, speedup (parsing only). --- cdc.d | 4 ++-- dyaml/parser.d | 2 +- dyaml/queue.d | 6 +++--- dyaml/reader.d | 45 +++++++++++++++++++++++++-------------- dyaml/scanner.d | 36 +++++++++++++++++++++---------- dyaml/{ => std}/variant.d | 0 6 files changed, 60 insertions(+), 33 deletions(-) rename dyaml/{ => std}/variant.d (100%) diff --git a/cdc.d b/cdc.d index 960a3a4..cc993aa 100755 --- a/cdc.d +++ b/cdc.d @@ -155,8 +155,8 @@ void main(string[] args) if(args.length > 0 && args[$ - 1][0] != '-'){target = args[$ - 1];} string[] dbg = ["-debug", "-gc"]; - string[] optimize = ["-O", "-inline", "-release"]; - string[] profile = ["-O", "-inline", "-release", "-gc"]; + string[] optimize = ["-O", "-inline", "-release", "-noboundscheck"]; + string[] profile = ["-O", "-release", "-noboundscheck", "-gc"]; string[] lib_src = ["dyaml/", "yaml.d"]; void compile_(string[] args, string[] files) diff --git a/dyaml/parser.d b/dyaml/parser.d index 7c30895..89f27dc 100644 --- a/dyaml/parser.d +++ b/dyaml/parser.d @@ -219,7 +219,7 @@ final class Parser if(!currentEvent_.isNull) { immutable Event result = currentEvent_; - clear(currentEvent_); + currentEvent_.id = EventID.Invalid; return result; } assert(false, "No event left to get"); diff --git a/dyaml/queue.d b/dyaml/queue.d index 85b3a26..5164472 100644 --- a/dyaml/queue.d +++ b/dyaml/queue.d @@ -185,7 +185,7 @@ T* allocate(T, Args...)(Args args) T* ptr = cast(T*)malloc(T.sizeof); *ptr = T(args); //The struct might contain references to GC-allocated memory, so tell the GC about it. - if(hasIndirections!T){GC.addRange(cast(void*)ptr, T.sizeof);} + static if(hasIndirections!T){GC.addRange(cast(void*)ptr, T.sizeof);} return ptr; } @@ -193,8 +193,8 @@ T* allocate(T, Args...)(Args args) void free(T)(T* ptr) { //GC doesn't need to care about any references in this struct anymore. - if(hasIndirections!T){GC.removeRange(cast(void*)ptr);} - clear(*ptr); + static if(hasIndirections!T){GC.removeRange(cast(void*)ptr);} + static if(hasMember!(T, "__dtor")){clear(*ptr);} std.c.stdlib.free(ptr); } diff --git a/dyaml/reader.d b/dyaml/reader.d index 6b330f6..47227dd 100644 --- a/dyaml/reader.d +++ b/dyaml/reader.d @@ -168,24 +168,38 @@ final class Reader * Note: This gets only a "view" into the internal buffer, * which WILL get invalidated after other Reader calls. * - * Params: length = Number of characters to get. + * Params: length = Number of characters to get. * - * Returns: Characters starting at current position. - * - * Throws: ReaderException if trying to read past the end of the stream - * or if invalid data is read. + * Returns: Characters starting at current position or an empty slice if out of bounds. */ - dstring prefix(in size_t length) + const(dstring) prefix(in size_t length) { - if(length == 0){return "";} - if(buffer_.length <= bufferOffset_ + length) + return slice(0, length); + } + + /** + * Get a slice view of the internal buffer. + * + * Note: This gets only a "view" into the internal buffer, + * which WILL get invalidated after other Reader calls. + * + * Params: start = Start of the slice relative to current position. + * end = End of the slice relative to current position. + * + * Returns: Slice into the internal buffer or an empty slice if out of bounds. + */ + const(dstring) slice(size_t start, size_t end) + { + if(buffer_.length <= bufferOffset_ + end) { - updateBuffer(length); + updateBuffer(end); } - const end = min(buffer_.length, bufferOffset_ + length); - //need to duplicate as we change buffer content with C functions - //and could end up with returned string referencing changed data - return cast(dstring)buffer_[bufferOffset_ .. end]; + end += bufferOffset_; + start += bufferOffset_; + end = min(buffer_.length, end); + if(end <= start){return "";} + + return cast(dstring)buffer_[start .. end]; } /** @@ -275,7 +289,7 @@ final class Reader * If there are not enough characters in the stream, it will get * as many as possible. * - * Params: length = Mimimum number of characters we need to read. + * Params: length = Number of characters we need to read. * * Throws: ReaderException if trying to read past the end of the stream * or if invalid data is read. @@ -324,7 +338,7 @@ final class Reader ///Get next character from the stream. dchar getDChar() { - switch(encoding_) + final switch(encoding_) { case Encoding.UTF_8: //Temp buffer for moving data in rawBuffer8_. @@ -389,7 +403,6 @@ final class Reader available_ -= 4; stream_.read(result); return result; - default: assert(false); } } diff --git a/dyaml/scanner.d b/dyaml/scanner.d index 7c05e87..bb8662f 100644 --- a/dyaml/scanner.d +++ b/dyaml/scanner.d @@ -15,6 +15,7 @@ import core.stdc.string; import std.algorithm; import std.array; +import std.container; import std.conv; import std.ascii : isAlphaNum, isDigit, isHexDigit; import std.exception; @@ -123,7 +124,7 @@ final class Scanner ///Current indentation level. int indent_ = -1; ///Past indentation levels. Used as a stack. - int[] indents_; + Array!int indents_; ///Processed tokens not yet emitted. Used as a queue. Queue!Token tokens_; @@ -164,7 +165,6 @@ final class Scanner { clear(tokens_); clear(indents_); - indents_ = null; clear(possibleSimpleKeys_); possibleSimpleKeys_ = null; clear(appender_); @@ -404,7 +404,7 @@ final class Scanner while(indent_ > column) { indent_ = indents_.back; - indents_.popBack(); + indents_.length = indents_.length - 1; tokens_.push(blockEndToken(reader_.mark, reader_.mark)); } } @@ -779,7 +779,6 @@ final class Scanner (c == '-' || (flowLevel_ == 0 && "?:"d.canFind(c)))); } - ///Move to the next non-space character. void findNextNonSpace() { @@ -1266,13 +1265,23 @@ final class Scanner mixin FastCharSearch!" \t\0\n\r\u0085\u2028\u2029\'\"\\"d search; - while(!search.canFind(c)) + //This is an optimized way of writing: + //while(!search.canFind(reader_.peek(length))){++length;} + outer: for(;;) { - ++length; - c = reader_.peek(length); + const slice = reader_.slice(length, length + 32); + enforce(slice.length > 0, + new Error("While reading a flow scalar", startMark, + "reached end of file", reader_.mark)); + foreach(ch; slice) + { + if(search.canFind(ch)){break outer;} + ++length; + } } - if(length > 0){appender_.put(reader_.get(length));} + appender_.put(reader_.prefix(length)); + reader_.forward(length); c = reader_.peek(); if(quotes == ScalarStyle.SingleQuoted && @@ -1338,14 +1347,15 @@ final class Scanner { uint length = 0; while(" \t"d.canFind(reader_.peek(length))){++length;} - const whitespaces = reader_.get(length); + const whitespaces = reader_.prefix(length + 1); - dchar c = reader_.peek(); + const c = whitespaces[$ - 1]; enforce(c != '\0', new Error("While scanning a quoted scalar", startMark, "found unexpected end of stream", reader_.mark)); if("\n\r\u0085\u2028\u2029"d.canFind(c)) { + reader_.forward(length); const lineBreak = scanLineBreak(); const breaks = scanFlowScalarBreaks(startMark); @@ -1353,7 +1363,11 @@ final class Scanner else if(breaks.length == 0){appender_.put(' ');} appender_.put(breaks); } - else{appender_.put(whitespaces);} + else + { + appender_.put(whitespaces[0 .. $ - 1]); + reader_.forward(length); + } } ///Scan line breaks in a flow scalar. diff --git a/dyaml/variant.d b/dyaml/std/variant.d similarity index 100% rename from dyaml/variant.d rename to dyaml/std/variant.d