viewmail-info
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[VM] [XEMACS PATCH] Be lazy about calling marker_position() in bytecode_


From: Aidan Kehoe
Subject: [VM] [XEMACS PATCH] Be lazy about calling marker_position() in bytecode_arithcompare()
Date: Sun, 1 Dec 2013 11:31:41 +0000

PATCH 21.5

This change improves performance for VM with large folder a little, though
it’s not a complete solution. In particular, when hitting q in a modified
folder with index files turned on and non-ASCII bytes in the buffer,
#'vm-sort-compare-physical-order is called about 5 N times for N messages,
giving 10 N calls to marker-position, which is expensive.

This shows up as char-byte conversion in XEmacs profiling, and my below
change improves this, such that the majority of the time in the described
context is now in #'write-file-internal, not char-byte conversion.

diff -r 4e69b24a2301 src/bytecode.c
--- a/src/bytecode.c    Mon Oct 28 16:03:53 2013 +0100
+++ b/src/bytecode.c    Sun Dec 01 11:16:59 2013 +0000
@@ -287,7 +287,7 @@
 bytecode_arithcompare (Lisp_Object obj1, Lisp_Object obj2)
 {
 #ifdef WITH_NUMBER_TYPES
-  switch (promote_args (&obj1, &obj2))
+  switch (promote_args_lazy (&obj1, &obj2))
     {
     case FIXNUM_T:
       {
@@ -306,6 +306,13 @@
     case BIGFLOAT_T:
       return bigfloat_cmp (XBIGFLOAT_DATA (obj1), XBIGFLOAT_DATA (obj2));
 #endif
+    case MARKER_T:
+      {
+       Bytebpos ival1 = byte_marker_position (obj1);
+       Bytebpos ival2 = byte_marker_position (obj2);
+       return ival1 < ival2 ? -1 : ival1 > ival2 ? 1 : 0;
+      }
+
     default: /* FLOAT_T */
       {
        double dval1 = XFLOAT_DATA (obj1), dval2 = XFLOAT_DATA (obj2);
@@ -320,7 +327,19 @@
 
     if      (FIXNUMP    (obj1)) ival1 = XFIXNUM  (obj1);
     else if (CHARP   (obj1)) ival1 = XCHAR (obj1);
-    else if (MARKERP (obj1)) ival1 = marker_position (obj1);
+    else if (MARKERP (obj1))
+      {
+       /* Handle markers specially, since #'marker-position can be O(N): */
+       if (MARKERP (obj2)
+           && (XMARKER (obj1)->buffer == XMARKER (obj2)->buffer))
+         {
+           Bytebpos ival1 = byte_marker_position (obj1);
+           Bytebpos ival2 = byte_marker_position (obj2);
+           return ival1 < ival2 ? -1 : ival1 > ival2 ? 1 : 0;
+         }
+
+       ival1 = marker_position (obj1);
+      }
     else goto arithcompare_float;
 
     if      (FIXNUMP    (obj2)) ival2 = XFIXNUM  (obj2);
diff -r 4e69b24a2301 src/data.c
--- a/src/data.c        Mon Oct 28 16:03:53 2013 +0100
+++ b/src/data.c        Sun Dec 01 11:16:59 2013 +0000
@@ -936,10 +936,10 @@
     {                                                          \
       obj1 = args[i - 1];                                      \
       obj2 = args[i];                                          \
-      switch (promote_args (&obj1, &obj2))                     \
+      switch (promote_args_lazy (&obj1, &obj2))                        \
        {                                                       \
        case FIXNUM_T:                                          \
-         if (!(XREALFIXNUM (obj1) c_op XREALFIXNUM (obj2)))            \
+         if (!(XREALFIXNUM (obj1) c_op XREALFIXNUM (obj2)))    \
            return Qnil;                                        \
          break;                                                \
        BIGNUM_CASE (op)                                        \
@@ -949,11 +949,20 @@
            return Qnil;                                        \
          break;                                                \
        BIGFLOAT_CASE (op)                                      \
+        case MARKER_T:                                          \
+          if (!(byte_marker_position (obj1) c_op                \
+                byte_marker_position (obj2)))                   \
+            return Qnil;                                        \
+          break;                                                \
        }                                                       \
     }                                                          \
   return Qt;                                                   \
 }
 #else /* !WITH_NUMBER_TYPES */
+/* We don't convert markers lazily here, although we could. It's more
+   important that we do this lazily in bytecode, which is the case; see
+   bytecode_arithcompare().
+   */
 #define ARITHCOMPARE_MANY(c_op,op)                             \
 {                                                              \
   int_or_double iod1, iod2, *p = &iod1, *q = &iod2;            \
diff -r 4e69b24a2301 src/number.h
--- a/src/number.h      Mon Oct 28 16:03:53 2013 +0100
+++ b/src/number.h      Sun Dec 01 11:16:59 2013 +0000
@@ -373,11 +373,40 @@
 
 EXFUN (Fcanonicalize_number, 1);
 
-enum number_type {FIXNUM_T, BIGNUM_T, RATIO_T, FLOAT_T, BIGFLOAT_T};
+#define NUMBER_TYPES(prefix) prefix##FIXNUM_T, prefix##BIGNUM_T, \
+    prefix##RATIO_T, prefix##FLOAT_T, prefix##BIGFLOAT_T
+
+enum number_type { NUMBER_TYPES() };
+enum lazy_number_type { NUMBER_TYPES(LAZY_), MARKER_T };
 
 extern enum number_type get_number_type (Lisp_Object);
 extern enum number_type promote_args (Lisp_Object *, Lisp_Object *);
 
+/* promote_args() *always* converts a marker argument to an integer.
+
+   Unfortunately, for a marker with byte position N, getting the (character)
+   marker position is O(N). Getting the character position isn't necessary
+   for bytecode_arithcompare() if two markers being compared are in the same
+   buffer, comparing the byte position is enough.
+
+   It is necessary for those operations implemented by bytecode_arithop(),
+   though, with the exception that Bmax and Bmin could be changed to call
+   marker-position once rather than twice. */
+DECLARE_INLINE_HEADER (
+enum lazy_number_type
+promote_args_lazy (Lisp_Object *obj1, Lisp_Object *obj2))
+{
+  if (MARKERP (*obj1) && MARKERP (*obj2) &&
+      XMARKER (*obj1)->buffer == XMARKER (*obj2)->buffer)
+    {
+      return MARKER_T;
+    }
+
+  return (enum lazy_number_type) promote_args (obj1, obj2);
+}
+
+#undef NUMBER_TYPES
+
 #ifdef WITH_NUMBER_TYPES
 DECLARE_INLINE_HEADER (
 int


-- 
‘Liston operated so fast that he once accidentally amputated an assistant’s
fingers along with a patient’s leg, […] The patient and the assistant both
died of sepsis, and a spectator reportedly died of shock, resulting in the
only known procedure with a 300% mortality.’ (Atul Gawande, NEJM, 2012)



reply via email to

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