[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: How to read integers from file faster?
From: |
Mark H Weaver |
Subject: |
Re: How to read integers from file faster? |
Date: |
Sat, 31 Aug 2013 04:59:48 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) |
Darren Hoo <address@hidden> writes:
> It is way too slow to read numbers from a file simply by using `read'
Indeed. Looking at the code, I can see a lot of room for improvement,
especially in 'string->number' (which is used also by 'read'). I've
added an item to my TODO list to optimize this. Hopefully by 2.0.10 or
2.0.11, it will be faster.
> Are there any primitives in Guile that is equivalent to C's scanf?
I'm afraid there's currently nothing that will read integers very fast.
I experimented with using the Dynamic FFI to wrap various C functions,
but was unable to achieve more than a 2x improvement this way.
In the meantime, please remember that part of Guile's philosophy
(inherited from Emacs) is to use C extensions where necessary for
performance critical bits. For the basics of how to do this, see:
https://www.gnu.org/software/guile/manual/html_node/C-Extensions.html
As an example, I've attached a small C extension that uses 'fscanf' to
read integers from a file until EOF is reached, and returns them as a
list. Here's how to compile and load it on GNU/Linux:
--8<---------------cut here---------------start------------->8---
address@hidden:~$ gcc -shared -o read_integers_from_file.so -fPIC
read_integers_from_file.c $(pkg-config --cflags guile-2.0)
address@hidden:~$ guile
GNU Guile 2.0.9
Copyright (C) 1995-2013 Free Software Foundation, Inc.
Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.
Enter `,help' for help.
scheme@(guile-user)> (load-extension "./read_integers_from_file.so"
"scm_init_read_integers_from_file")
scheme@(guile-user)> (use-modules (read-integers-from-file))
scheme@(guile-user)> (define lst (read-integers-from-file "rnd.txt"))
--8<---------------cut here---------------end--------------->8---
Note that although this code does partial error checking, it cannot cope
with integers that don't fit in a C long, and it also assumes that the
file is properly formatted.
Regards,
Mark
#include <stdio.h>
#include <libguile.h>
static SCM
read_integers_from_file (SCM filename)
{
char *fname = scm_to_locale_string (filename);
FILE *f = fopen (fname, "r");
SCM result = SCM_EOL;
int err = 0;
long num;
if (f == NULL)
err = 1;
else
{
while (fscanf (f, "%dl", &num) == 1)
result = scm_cons (scm_from_long (num), result);
if (ferror (f))
err = 1;
if (fclose (f))
err = 1;
}
free (fname);
if (err)
scm_syserror ("read-integers-from-file");
return scm_reverse_x (result, SCM_EOL);
}
void
init_read_integers_from_file (void *unused)
{
scm_c_define_gsubr ("read-integers-from-file", 1, 0, 0,
read_integers_from_file);
scm_c_export ("read-integers-from-file", NULL);
}
void
scm_init_read_integers_from_file ()
{
scm_c_define_module ("read-integers-from-file",
init_read_integers_from_file, NULL);
}