From: Francois-Rene Rideau
Subject: Concurrency, introspection, and optimization
Date: 
Message-ID: <8766jmkrs2.fsf@Kadath.augustin.thierry>
One problem with the semantic specification of dynamic languages
is the interaction between dynamic modification of code and concurrency,
which, if not specified in clean ways, can lead to making impossible
(or very difficult, through dynamic invalidation) many of the optimizations
that we feel are "natural".

Such optimizations include implementing tail-self-recursion by jumping back,
moving loop invariants outside of the loop, doing strength reduction,
deforestation, and a lot of other well-known program transforms that may
dramatically enhance runtime performance.

The problem is that if some global/shared variable is observable (or worse,
modifiable) from another thread (including the debugger and/or dynamic
listener), then it must be consistently updated (or worse, refetch from
memory), least the semantics of concurrent dynamic access be inconsistent.
In other words, "local constants" and more generally "local invariants"
of which you expect your compiler to take advantage are no longer
constant nor invariant anymore, due to the possibility of spurious
modifications by a concurrent thread.
Lazy update or refetch (triggered by a meta-object that intercepts the
access from the other thread) is a general technique to enable the
optimization while still allowing dynamic access, but it is either limited
to simple cases, or it requires complex program transformations that should
be generated in a way covariant with the optimizations applied.
Either way, there is a non-negligible cost to dynamic access in either
runtime performance loss or compiler complexity.

ANSI CL describes an essentially single-threaded language, where the only
modifications are done in the debugger, and any performance/optimization
questions are moot during debugging. But in real-life, we are more and more
to face programs with concurrent behavior, and the question gets more and
more important as applications are more and more multi-threaded.

Languages like C provide efficiency in the easy case by not tackling
the hard case at all and basically forbidding any dynamic access to code,
unless explicitly protected by very expensive awkward locking mechanisms.

I'd like to know if there are any conventions, tradition, literature, etc,
about how such things are done in LISP, both "real-life" implementations
or research implementations.

Erlang specifies has a module system, and specifies that unqualified (local)
calls may be optimized away, while explicitly module-qualified calls
(external or local) are to be done through an indirection.
This seems to match the expected behavior in LISP, where lexical functions
or variables could be optimized away, while calls to global/special functions
must go through explicit indirections.
People whose coding style involves giving global names to helper functions,
or using too many special/global variables may thus find their code
to be significantly slower than people using labels and lexical variables.

Does the Dylan specifications tackle this problem?
I believe it does, through sealed classes.

[ Fran�ois-Ren� �VB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[  TUNES project for a Free Reflective Computing System  | http://tunes.org  ]
Oint le vilain, il te poindra. Point le vilain, il te oindra.
	-- (Sagesse du Moyen-�ge)

From: Rainer Joswig
Subject: Re: Concurrency, introspection, and optimization
Date: 
Message-ID: <joswig-A93D9F.17155111012001@news.is-europe.net>
In article <··············@Kadath.augustin.thierry>, Francois-Rene 
Rideau <·······@SPAM.tunes.org> wrote:

> One problem with the semantic specification of dynamic languages
> is the interaction between dynamic modification of code and concurrency,
> which, if not specified in clean ways, can lead to making impossible
> (or very difficult, through dynamic invalidation) many of the optimizations
> that we feel are "natural".

Just imagine two threads reading 

- the same DEFCLASS form
- a slightly different DEFCLASS form for the same class
- a different DEFCLASS form for different classes

What happens? Is the CLOS implementation thread safe?

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/
From: Espen Vestre
Subject: Re: Concurrency, introspection, and optimization
Date: 
Message-ID: <w6vgrlcipm.fsf@wallace.ws.nextra.no>
Rainer Joswig <······@corporate-world.lisp.de> writes:

> Just imagine two threads reading 
> 
> - the same DEFCLASS form
> - a slightly different DEFCLASS form for the same class
> - a different DEFCLASS form for different classes
> 
> What happens? Is the CLOS implementation thread safe?

I don't think so, at least I'm not betting on it (but let each thread
(that wants to define classes) seize a global lock).
-- 
  (espen)
From: Rainer Joswig
Subject: Re: Concurrency, introspection, and optimization
Date: 
Message-ID: <joswig-232140.20085712012001@news.is-europe.net>
In article <··············@wallace.ws.nextra.no>, Espen Vestre 
<·····@*do-not-spam-me*.vestre.net> wrote:

> Rainer Joswig <······@corporate-world.lisp.de> writes:
> 
> > Just imagine two threads reading 
> > 
> > - the same DEFCLASS form
> > - a slightly different DEFCLASS form for the same class
> > - a different DEFCLASS form for different classes
> > 
> > What happens? Is the CLOS implementation thread safe?
> 
> I don't think so, at least I'm not betting on it (but let each thread
> (that wants to define classes) seize a global lock).

The Symbolics implementation of CLOS seems to be written in
thread safe style.

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/
From: Robert Virding
Subject: Re: Concurrency, introspection, and optimization
Date: 
Message-ID: <3a62e30c$1@news.pi.se>
In article <··············@Kadath.augustin.thierry>,
 Francois-Rene Rideau <·······@SPAM.tunes.org> writes:
>Erlang specifies has a module system, and specifies that unqualified (local)
>calls may be optimized away, while explicitly module-qualified calls
>(external or local) are to be done through an indirection.
>This seems to match the expected behavior in LISP, where lexical functions
>or variables could be optimized away, while calls to global/special functions
>must go through explicit indirections.

Also, there are no global variables in Erlang, all data is owned by a
process.  This simplifies concurrency and distribution.  Most things
work transparently over diributed nodes.

(Actually ETS tables are implemented as a global data structure, but
they behave as if they were owned by a process, in fact they can be
implemented with processes.)

	Robert

-- 
Robert Virding                          Tel: +46 (0)8 545 55 017
Alteon Web Systems                      Email: ··@bluetail.com
S:t Eriksgatan 44                       WWW: http://www.bluetail.com/~rv
SE-112 34 Stockholm, SWEDEN
"Folk s�ger att jag inte bryr mig om n�gonting, men det skiter jag i".