Skip to content

Instantly share code, notes, and snippets.

@jcward
Last active June 6, 2017 07:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jcward/b061b64cfafd277bd3105dacb040a5ef to your computer and use it in GitHub Desktop.
Save jcward/b061b64cfafd277bd3105dacb040a5ef to your computer and use it in GitHub Desktop.
Haxe String.split() is 100x slower in macro context than runtime?!
# 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
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;
}
}
#!/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