Last active
June 6, 2017 07:41
-
-
Save jcward/b061b64cfafd277bd3105dacb040a5ef to your computer and use it in GitHub Desktop.
Haxe String.split() is 100x slower in macro context than runtime?!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Any text.txt file will do, e.g. just grab a web page: | |
> wget https://en.wikipedia.org/wiki/List_of_Dewey_Decimal_classes -O text.txt | |
>haxe -x Main.hx | |
Main.hx:30: Macro time! | |
Main.hx:20: Std split: 172500 words in 8.83726906776428223 | |
Main.hx:25: Custom split: 172500 words in 5.53304815292358398 | |
Main.hx:11: Runtime! | |
Main.hx:20: Std split: 172500 words in 0.077721118927002 | |
Main.hx:25: Custom split: 172500 words in 1.07498717308044 | |
Explanations? Ideas? | |
Adding insult to injury, Ruby's 2.5X faster than Neko runtime: | |
>ruby split.rb | |
Ruby: 172500 words in 0.02813100814819336 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Main | |
{ | |
public static var text:String; | |
public static function main() | |
{ | |
var text = ""; | |
in_macro(); | |
trace("Runtime!"); | |
benchmark(); | |
} | |
public static function benchmark() | |
{ | |
text = sys.io.File.getContent("text.txt"); | |
var t0 = haxe.Timer.stamp(); | |
var cnt = std_split(text); | |
trace(" Std split: "+cnt+" words in "+(haxe.Timer.stamp()-t0)); | |
text = sys.io.File.getContent("text.txt"); | |
var t0 = haxe.Timer.stamp(); | |
var cnt = custom_split(text); | |
trace("Custom split: "+cnt+" words in "+(haxe.Timer.stamp()-t0)); | |
} | |
public static macro function in_macro() | |
{ | |
trace("Macro time!"); | |
benchmark(); | |
return macro $v{ 0 }; | |
} | |
public static function std_split(text:String) | |
{ | |
var cnt = 0; | |
for (i in 0...100) { | |
var lines = text.split("\n"); | |
cnt += lines.length; | |
} | |
return cnt; | |
} | |
public static function custom_split(text:String) | |
{ | |
var cnt = 0; | |
for (i in 0...100) { | |
var lines = dsplt(text, "\n"); | |
cnt += lines.length; | |
} | |
return cnt; | |
} | |
static public function dsplt(src:String, delim:String) | |
{ | |
var lines = []; | |
var pos = []; | |
var l = delim.length; | |
var i = 0; | |
inline function eq_at(idx:Int):Bool | |
{ | |
var ii=0; | |
var rtn = true; | |
while (ii<l) { | |
if (StringTools.fastCodeAt(src,idx+ii)!=StringTools.fastCodeAt(delim,ii)) { rtn = false; break; } | |
ii++; | |
} | |
return rtn; | |
} | |
while (i<src.length) { | |
if (eq_at(i)) { | |
pos.push(i); | |
i += l; | |
} else { | |
i++; | |
} | |
} | |
var last = 0; | |
for (p in pos) { | |
lines.push(src.substring(last, p)); | |
last = p+l; | |
} | |
lines.push(src.substring(last, src.length)); | |
return lines; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
contents = File.read("text.txt") | |
t0 = Time.now.to_f | |
cnt = 0 | |
0.upto(99) { | |
cnt += contents.split("\n").length | |
} | |
puts " Ruby: #{ cnt } words in #{ Time.now.to_f-t0 }" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment