another question, and a small patch

Vladimir Vukicevic vladimir@helixcode.com
Mon, 12 Jun 2000 11:32:18 -0400


Okay, I got my issues worked out -- now, it's mainly speed. My code
basically does this.. reads 128-byte blocks from an input file, does a
gcry_mpi_scan on the blocks, then makes a SEXP from that MPI, does
a pk_encrypt(), and then writes the resulting MPI a/b pair to a
file. (I'm using ElGamal.) The problem is that it's ridiculously slow;
encoding a simple 6k file takes about 8 seconds, which is completely
unacceptable. By contrast, gpg -e takes 0.06 sec. So, I'm obviously
doing something that's rather stupid. I'm currently read()'ing blocks
one by one, an optimization would be to mmap the input file; but that
shouldn't be that big of a bottleneck. Any thoughts on this speed
problem?

I also ran into some problems with the sexp implementation.. The
problem is if you have a sexp such as that returned from pk_encrypt:
(enc-data (elg (a MPI) (b MPI))), there was no way previously to get
at any of that data using the car/cdr functions. You had to search for
the token. These patches make car 'do the right thing' (I think), by
checking to see if the first elt is a list, and if so to give you the
list itself, not just the same object back. Also, sexp_release wasn't
implemented, so I implemented that as well. Plus, the small patch that
attempts to stick the right export symbols into the .so (it still
doesn't work quite right).


Index: gcrypt/Makefile.am
===================================================================
RCS file: /home/koch/cvs/gnupg/gcrypt/Makefile.am,v
retrieving revision 1.13
diff -u -r1.13 Makefile.am
--- gcrypt/Makefile.am	2000/01/31 15:26:58	1.13
+++ gcrypt/Makefile.am	2000/06/12 15:21:51
@@ -43,8 +43,14 @@
 # libtool's --export-symbols-regex does not work in 1.3.2
 # so we do it ourself
 libgcrypt.sym: $(libgcrypt_la_OBJECTS)
-	    $(NM) $(libgcrypt_la_OBJECTS) \
-	      | $(AWK) '$$2=="T" && $$3 ~ /^gcry_/ {print $$3}' >libgcrypt.sym
+	$(NM) $(libgcrypt_la_OBJECTS) \
+	      | $(AWK) '$$2=="T" && $$3 ~ /^gcry_/ {print $$3}' >libgcrypt-local.sym
+	(cd ../mpi; $(NM) *.lo | $(AWK) '$$2=="T" && $$3 ~ /^gcry_/ {print $$3}' > libmpi.sym)
+	(cd ../cipher; $(NM) *.lo | $(AWK) '$$2=="T" && $$3 ~ /^gcry_/ {print $$3}' > libcipher.sym)
+	(cd ../util; $(NM) *.lo | $(AWK) '$$2=="T" && $$3 ~ /^gcry_/ {print $$3}' > libutil.sym)
+	cat libgcrypt-local.sym ../mpi/libmpi.sym ../cipher/libcipher.sym ../util/libutil.sym > libgcrypt.sym
+
+
 
 
 
Index: gcrypt/sexp.c
===================================================================
RCS file: /home/koch/cvs/gnupg/gcrypt/sexp.c,v
retrieving revision 1.9
diff -u -r1.9 sexp.c
--- gcrypt/sexp.c	2000/01/27 16:50:43	1.9
+++ gcrypt/sexp.c	2000/06/12 15:21:51
@@ -219,7 +219,35 @@
 void
 gcry_sexp_release( GCRY_SEXP sexp )
 {
-    /* FIXME! */
+     /* Note that this will do a deep release, i.e. release the mpi's
+      * and data buf's that are pointed to by this sexp. This, in theory,
+      * is the wrong thing to do -- the "Right Thing" would be to do
+      * refcounting here.
+      */
+
+     if (sexp == NULL) return;
+
+#if 0
+     fprintf (stderr, "SEXP_RELEASE: ");
+     gcry_sexp_dump (sexp);
+#endif
+
+     /* Release across */
+     gcry_sexp_release (sexp->next);
+
+     /* Then release down, if present */
+     if (sexp->type == ntLIST) {
+	  gcry_sexp_release (sexp->u.list);
+     } else if (sexp->type == ntMPI) {
+	  gcry_mpi_release (sexp->u.mpi);
+     } else if (sexp->type == ntDATA) {
+	  /* Nothing special -- taken care of in following g10_free */
+     } else {
+	  /* there should be no other types */
+	  BUG();
+     }
+
+     g10_free (sexp);
 }
 
 
@@ -478,7 +506,10 @@
 GCRY_SEXP
 gcry_sexp_car( GCRY_SEXP list )
 {
-    return list;
+     if( list && list->type == ntLIST )
+	  list = list->u.list;
+     
+     return list;
 }
 
 /****************
@@ -524,6 +555,8 @@
 GCRY_SEXP
 gcry_sexp_cdr( GCRY_SEXP list )
 {
+    if( list && list->type == ntLIST && !list->next )
+	list = list->u.list;
     if( list && (list = list->next) )
 	return list;
     return NULL;