guile-user
[Top][All Lists]
Advanced

[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);
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]