I've decided to compare Hare app and the same app written on Dart.
Both are compiled. Both have the same logic (as far as I can see). But
hare app is x3 time slowly than Dart.
```dart
import 'dart:io';
void main() {
File inputFile = File('in.xml');
List<String> lines = inputFile.readAsLinesSync();
List<String> updatedLines = lines.map((line) =>
line.replaceAll('ns', '')).toList();
File outputFile = File('out.xml');
outputFile.writeAsStringSync(updatedLines.join('\n'));
print('Finished');
}
```
```hare
use fmt;
use io;
use bufio;
use memio;
use os;
use fs;
use strings;
use types;
use encoding::utf8;
export fn main() void = {
const new_file_buf = memio::dynamic();
const new_file = os::create("out.xml", fs::mode::USER_RW)!;
const file = os::open(os::args[1])!;
const scanner = bufio::newscanner(file, types::SIZE_MAX);
for(true) {
let line = match(bufio::scan_line(&scanner)) {
case let line: const str =>
line = strings::replace(line, "ns", "");
io::write(&new_file_buf,
strings::toutf8(line))!;
yield void;
case io::EOF => break;
};
};
io::write(new_file, memio::buffer(&new_file_buf))!;
};
```
What can be the reason?
Without profiling it myself, a few things come to mind.
- You are first writing everything to a memio buffer, then writing again
to the output file. Why not just write straight out to a (consider
buffered) output file?
- line = strings::replace(line, ...) is returning a new, freshly
allocated string (that you leak). Allocations aren't free.
- I think your current solution removes newlines? Is that really what
you want?
- If all you want to do is remove all "ns" from the input, one trick
would be to bufio::scan_bytes(&scanner, ['n', 's']), then simply
io::write it out.
This might be much quicker, but it might also just depend on your input
file:
use io;
use bufio;
use os;
use fs;
use types;
export fn main() void = {
const new_file = os::create("out.xml", fs::mode::USER_RW)!;
const file = os::open(os::args[1])!;
const scanner = bufio::newscanner(file, types::SIZE_MAX);
for(true) match(bufio::scan_bytes(&scanner, ['n', 's'])!) {
case io::EOF =>
break;
case let line: []u8 =>
io::write(new_file, line)!;
};
};
If that's not cutting it for you, then you have to break out a profiler.
I have had luck with callgrind + hare.
i'm also not particularly pleased with hare's performance in general.
i brought this up in #hare-dev a few days ago, and i'm planning to write
something up for the hare-dev mailing list asp in the future, but i
suspect poor codegen for aggregate returns as being at the very least
the easiest next step for improving perf. i think triallax was looking
into that, feel free to reach out to him if you want to know more or
help