From: Dmitry Antipov <dmantipov@yandex.ru>
To: Emacs development discussions <emacs-devel@gnu.org>
Subject: Benchmarking temporary Lisp objects [Was: Re: [RFC] temporary Lisp_Strings]
Date: Wed, 03 Sep 2014 14:23:29 +0400 [thread overview]
Message-ID: <5406EC21.4060200@yandex.ru> (raw)
In-Reply-To: <jwv8um2expp.fsf-monnier+emacs@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 1098 bytes --]
To whom it may concern, I decided to start from conses and vectors
just because this is simpler than strings. My experimental stuff
is attached, and typical benchmark output may be something like:
Average of 100: stack allocation is 6.879408 times faster for conses
Average of 1000: stack allocation is 7.390145 times faster for conses
Average of 10000: stack allocation is 4.154356 times faster for conses
Average of 100000: stack allocation is 2.417694 times faster for conses
Average of 10: stack allocation is 11.535833 times faster for vectors
Average of 100: stack allocation is 4.731400 times faster for vectors
Average of 1000: stack allocation is 1.443268 times faster for vectors
Note that this is sustained allocation speed; since we're unlikely to
allocate large amounts of Lisp data on stack, real speedup may vary.
Questions:
1) Should alloca_vector fallback to Fmake_vector for large vectors?
2) Is there a way to rewrite alloca_xxx macros to avoid statement
expressions? IIUC this is not portable beyond gcc and compilers
that mimics it (clang, Intel's icc).
Dmitry
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cons_vector_benchmark.patch --]
[-- Type: text/x-patch; name="cons_vector_benchmark.patch", Size: 4044 bytes --]
=== modified file 'src/alloc.c'
--- src/alloc.c 2014-08-29 07:29:47 +0000
+++ src/alloc.c 2014-09-03 09:41:26 +0000
@@ -7118,8 +7118,76 @@
file, line, msg);
terminate_due_to_signal (SIGABRT, INT_MAX);
}
-#endif
-\f
+
+/* Stress alloca with inconveniently-sized requests and check
+ whether all allocated areas may be used for Lisp_Object. */
+
+static void
+verify_alloca (void)
+{
+ int i;
+ enum { ALLOCA_CHECK_MAX = 256 };
+ for (i = 0; i < ALLOCA_CHECK_MAX; i++)
+ {
+ char *ptr = alloca (i + 1);
+ eassert (valid_pointer_for_lisp_object (ptr));
+ }
+}
+
+#else /* not ENABLE_CHECKING */
+
+#define verify_alloca() ((void) 0)
+
+#endif /* ENABLE_CHECKING */
+
+DEFUN ("cons-benchmark", Fcons_benchmark, Scons_benchmark, 1, 1, 0,
+ doc: /* Benchmark cons allocation. */)
+ (Lisp_Object obj)
+{
+ double x, y;
+ ptrdiff_t i, max;
+ struct timespec ts;
+
+ CHECK_NUMBER (obj);
+ max = XINT (obj);
+
+ ts = current_timespec ();
+ for (i = 0, obj = Qnil; i < max; i++)
+ obj = Fcons (Qt, obj);
+ x = timespectod (timespec_sub (current_timespec (), ts));
+
+ ts = current_timespec ();
+ for (i = 0, obj = Qnil; i < max; i++)
+ obj = alloca_cons (Qt, obj);
+ y = timespectod (timespec_sub (current_timespec (), ts));
+
+ return Fcons (make_float (x), make_float (y));
+}
+
+DEFUN ("vector-benchmark", Fvector_benchmark, Svector_benchmark, 1, 1, 0,
+ doc: /* Benchmark vector allocation. */)
+ (Lisp_Object obj)
+{
+ double x, y;
+ ptrdiff_t i, max;
+ struct timespec ts;
+
+ CHECK_NUMBER (obj);
+ max = XINT (obj);
+
+ ts = current_timespec ();
+ for (i = 0, obj = Qnil; i < max; i++)
+ obj = Fmake_vector (make_number (i + 1), Qnil);
+ x = timespectod (timespec_sub (current_timespec (), ts));
+
+ ts = current_timespec ();
+ for (i = 0, obj = Qnil; i < max; i++)
+ obj = alloca_vector (i + 1, Qnil);
+ y = timespectod (timespec_sub (current_timespec (), ts));
+
+ return Fcons (make_float (x), make_float (y));
+}
+
/* Initialization. */
void
@@ -7129,6 +7197,8 @@
purebeg = PUREBEG;
pure_size = PURESIZE;
+ verify_alloca ();
+
#if GC_MARK_STACK || defined GC_MALLOC_CHECK
mem_init ();
Vdead = make_pure_string ("DEAD", 4, 4, 0);
@@ -7284,6 +7354,9 @@
#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
defsubr (&Sgc_status);
#endif
+
+ defsubr (&Scons_benchmark);
+ defsubr (&Svector_benchmark);
}
/* When compiled with GCC, GDB might say "No enum type named
=== modified file 'src/lisp.h'
--- src/lisp.h 2014-09-02 18:05:00 +0000
+++ src/lisp.h 2014-09-03 09:37:46 +0000
@@ -4533,6 +4533,37 @@
memory_full (SIZE_MAX); \
} while (false)
+/* True if Lisp_Object may be placed at P. Used only
+ under ENABLE_CHECKING and optimized away otherwise. */
+
+INLINE bool
+valid_pointer_for_lisp_object (void *p)
+{
+ uintptr_t v = (uintptr_t) p;
+ return !(USE_LSB_TAG ? (v & ~VALMASK) : v >> VALBITS);
+}
+
+/* Allocate Lisp_Cons on stack. */
+
+#define alloca_cons(head, tail) \
+ ({ struct Lisp_Cons *_c = alloca (sizeof *_c); \
+ eassert (valid_pointer_for_lisp_object (_c)); \
+ _c->car = (head), _c->u.cdr = (tail); \
+ make_lisp_ptr (_c, Lisp_Cons); })
+
+/* Allocate Lisp_Vector on stack, with respect to MAX_ALLOCA limit. */
+
+#define alloca_vector(slots, init) \
+ ({ struct Lisp_Vector *_v; \
+ ptrdiff_t _i, _n = header_size + (slots) * word_size; \
+ eassert (_n <= MAX_ALLOCA); \
+ _v = alloca (_n); \
+ eassert (valid_pointer_for_lisp_object (_v)); \
+ _v->header.size = (slots); \
+ for (_i = 0; _i < _v->header.size; _i++) \
+ _v->contents[_i] = init; \
+ make_lisp_ptr (_v, Lisp_Vectorlike); })
+
/* Loop over all tails of a list, checking for cycles.
FIXME: Make tortoise and n internal declarations.
FIXME: Unroll the loop body so we don't need `n'. */
[-- Attachment #3: cons-vector-benchmark.el --]
[-- Type: text/x-emacs-lisp, Size: 670 bytes --]
(defun cons-benchmark-test ()
(interactive)
(dolist (size '(100 1000 10000 100000))
(let ((avg 0.0))
(dotimes (i 1000)
(let ((data (cons-benchmark size)))
(setq avg (+ avg (/ (car data) (cdr data))))))
(message
"Average of %d: stack allocation is %f times faster for conses"
size (/ avg 1000.0)))))
(defun vector-benchmark-test ()
(interactive)
(dolist (size '(10 100 1000))
(let ((avg 0.0))
(dotimes (i 1000)
(let ((data (vector-benchmark size)))
(setq avg (+ avg (/ (car data) (cdr data))))))
(message
"Average of %d: stack allocation is %f times faster for vectors"
size (/ avg 1000.0)))))
next prev parent reply other threads:[~2014-09-03 10:23 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-02 12:55 [RFC] temporary Lisp_Strings Dmitry Antipov
2014-09-02 13:21 ` Andreas Schwab
2014-09-02 13:47 ` Dmitry Antipov
2014-09-02 14:14 ` Andreas Schwab
2014-09-02 15:00 ` Eli Zaretskii
2014-09-02 14:00 ` Stefan Monnier
2014-09-02 15:13 ` Dmitry Antipov
2014-09-02 17:32 ` Stefan Monnier
2014-09-03 10:23 ` Dmitry Antipov [this message]
2014-09-03 13:14 ` Benchmarking temporary Lisp objects [Was: Re: [RFC] temporary Lisp_Strings] Stefan Monnier
2014-09-03 14:39 ` Paul Eggert
2014-09-03 15:39 ` Dmitry Antipov
2014-09-03 16:42 ` Paul Eggert
2014-09-03 17:47 ` Stefan Monnier
2014-09-03 18:00 ` Paul Eggert
2014-09-04 4:59 ` Dmitry Antipov
2014-09-04 5:13 ` Paul Eggert
2014-09-04 5:51 ` Dmitry Antipov
2014-09-04 6:45 ` Paul Eggert
2014-09-04 13:11 ` Stefan Monnier
2014-09-04 13:37 ` Dmitry Antipov
2014-09-04 14:46 ` Dmitry Antipov
2014-09-04 16:03 ` Paul Eggert
2014-09-05 4:00 ` Dmitry Antipov
2014-09-05 4:24 ` Stefan Monnier
2014-09-05 9:28 ` Dmitry Antipov
2014-09-05 7:15 ` Paul Eggert
2014-09-05 9:16 ` Dmitry Antipov
2014-09-05 14:35 ` Paul Eggert
2014-09-05 15:35 ` Stefan Monnier
2014-09-08 10:33 ` Dmitry Antipov
2014-09-08 12:01 ` Dmitry Antipov
2014-09-08 13:30 ` Stefan Monnier
2014-09-08 12:44 ` Stefan Monnier
2014-09-08 13:30 ` Stefan Monnier
2014-09-02 14:37 ` [RFC] temporary Lisp_Strings Paul Eggert
2014-09-02 15:24 ` Dmitry Antipov
2014-09-02 15:28 ` Dmitry Antipov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5406EC21.4060200@yandex.ru \
--to=dmantipov@yandex.ru \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.