On Mon, Jul 20, 2009 at 21:07, Nicolas
Cannasse<[email protected]> wrote:
> If you use the same "way" of reading data (temporary buffer) I/O speed
> depends entirely of the disk speed, and maybe disk cache (in case you run
> the perl script after the neko one). There is simply no way to have 6 times
> faster I/O by using "tricks" and I don't see how Neko could be 6 times
> slower since it uses the same C API as Perl does.
The way may be slightly different. To read by line we had to do additional
processing while there is already a standard C function fgets for this, since
it is a common task. I wonder why you didn't exposed it in neko std library.
I was able to get significant speed increase (as compared to solutions
previously seen on the list) by adding the following to the std:
#include <string.h>
#define BUF_SIZE 1024
/**
file_gets : 'file -> string
<doc>Read a line from file.</doc>
**/
static value file_gets( value o ) {
fio *f;
val_check_kind(o, k_file);
f = val_file(o);
char buf[BUF_SIZE];
int length;
buffer b;
b = alloc_buffer(NULL);
if (fgets(buf, BUF_SIZE, f->io) == NULL)
file_error("file_gets", f);
buffer_append_sub(b, buf, length = strlen(buf));
while (buf[length-1] != '\n') {
if (fgets(buf, BUF_SIZE, f->io) == NULL) break;
buffer_append_sub(b, buf, length = strlen(buf));
}
return buffer_to_string(b);
}
DEFINE_PRIM(file_gets,1);
Probably could be written more optimally but anyway...
Neko code:
var file_stdin = $loader.loadprim("s...@file_stdin", 0);
var file_gets = $loader.loadprim("s...@file_gets", 1); // my primitive
readline = {
var in = file_stdin();
function() {
try { file_gets(in) }
catch _ null
}
}
while ((line = readline()) != null) _
Note that the above code is not compatible with those previously sent
to list because it returns a final newline as a part of the string.
If we want to remove it without sacrificing too much, we can not do it
in neko. But it can be done by replacing both occurrences of
buffer_append_sub(b, buf, length = strlen(buf));
with
buffer_append_sub(b, buf,
buf[(length = strlen(buf))-1] == '\n'
? length-1 : length);
After this change it works identically to the previous solutions but
much faster. As for me it's looks more than 3 times faster than last
one (but I didn't tested it thoroughly).
- Kacper
--
Neko : One VM to run them all
(http://nekovm.org)