Index: TODO
===================================================================
diff -u -rde5093e2960746e5727c31f6ef370f6389dbb51a -rb9000cff9206c8621e46524c2f12f8fc8fcb6f86
--- TODO	(.../TODO)	(revision de5093e2960746e5727c31f6ef370f6389dbb51a)
+++ TODO	(.../TODO)	(revision b9000cff9206c8621e46524c2f12f8fc8fcb6f86)
@@ -3726,6 +3726,12 @@
   of an extra method. By this change, the serializer works in
   constant time independent on the number of existing objects.
 
+nsf.c: 
+- reduce number of RUNTIME_STATE(interp) in favor of a variable.
+- make time of the definition of a method independent on the
+  number of defined instances (unless, when filters are defined)
+
+
 ========================================================================
 TODO:
 
@@ -3975,12 +3981,8 @@
      - currently, there are potential conflicts between slots and ensemble objects
      - provide a different place in the namesspaces could simplify this
 
-   * The speed of method definiton depends on the number of objects, 
-     since every defined method might be a filter, so FilterInvalidateObjOrders()
-     is called on each filter. It would be useful to keep a list of currently
-     defined filter names to perform the invalidation only when a method is defined
-     with the same name as the currently registered filter (that should be always
-     a small number).
+   * Cleanup the set of active filters when filters are removed (only relevant
+     for the speed of scripts with filters and a high number of instances)
 
    * Ensembles
      - It could be possible to reduce stack frames in ensembles. Just a
Index: generic/nsf.c
===================================================================
diff -u -r120b838888f00fe1a3130bf184fd079d06d89fa6 -rb9000cff9206c8621e46524c2f12f8fc8fcb6f86
--- generic/nsf.c	(.../nsf.c)	(revision 120b838888f00fe1a3130bf184fd079d06d89fa6)
+++ generic/nsf.c	(.../nsf.c)	(revision b9000cff9206c8621e46524c2f12f8fc8fcb6f86)
@@ -7368,6 +7368,63 @@
 }
 
 /*
+ *----------------------------------------------------------------------
+ * FilterAddActive --
+ *
+ *    Add a method name to the set of methods, which were used as filters in
+ *    the current interp. 
+ *
+ *    TODO: let the set shrink, when filters are removed.
+ *
+ * Results:
+ *    None.
+ *
+ * Side effects:
+ *    Adding or updating of a hash entry
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+FilterAddActive(Tcl_Interp *interp, CONST char *methodName) {
+  NsfRuntimeState *rst = RUNTIME_STATE(interp);
+  Tcl_HashEntry *hPtr;
+  int new, count;
+  
+  hPtr = Tcl_CreateHashEntry(&rst->activeFilterTablePtr, methodName, &new);
+
+  if (new) {
+    Tcl_SetHashValue(hPtr, INT2PTR(1));
+  } else {
+    count  = PTR2INT(Tcl_GetHashValue(hPtr));
+    Tcl_SetHashValue(hPtr, INT2PTR(count+1));
+  }
+}
+
+/*
+ *----------------------------------------------------------------------
+ * FilterIsActive --
+ *
+ *    Check, wether a method name is in the set of methods, which were used as
+ *    filters in the current interp.
+ *
+ * Results:
+ *    Boolean
+ *
+ * Side effects:
+ *    none
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+FilterIsActive(Tcl_Interp *interp, CONST char *methodName) {
+  NsfRuntimeState *rst = RUNTIME_STATE(interp);
+  Tcl_HashEntry *hPtr;
+  
+  hPtr = Tcl_CreateHashEntry(&rst->activeFilterTablePtr, methodName, NULL);
+  return (hPtr != NULL);
+}
+
+/*
  * append a filter command to the 'filterList' of an obj/class
  */
 static int
@@ -7407,6 +7464,7 @@
   /*fprintf(stderr, " +++ adding filter %s cl %p\n", ObjStr(nameObj), cl);*/
 
   new = CmdListAdd(filterList, cmd, cl, /*noDuplicates*/ 1);
+  FilterAddActive(interp, ObjStr(filterObj));
 
   if (guardObj) {
     GuardAdd(new, guardObj);
@@ -11753,7 +11811,9 @@
   if (cl) {
     NsfInstanceMethodEpochIncr("MakeMethod");
     /* could be a filter or filter inheritance ... update filter orders */
-    FilterInvalidateObjOrders(interp, cl);
+    if (FilterIsActive(interp, nameStr)) {
+      FilterInvalidateObjOrders(interp, cl);
+    }
   } else {
     NsfObjectMethodEpochIncr("MakeMethod");
     /* could be a filter => recompute filter order */
@@ -13874,7 +13934,6 @@
     /*MixinInvalidateObjOrders(interp, cl);*/
 
     CmdListRemoveList(&clopt->classFilters, GuardDel);
-    /*FilterInvalidateObjOrders(interp, cl);*/
 
     if (!recreate) {
       /*
@@ -23113,6 +23172,7 @@
 ExitHandler(ClientData clientData) {
   Tcl_Interp *interp = (Tcl_Interp *)clientData;
   int i, flags;
+  NsfRuntimeState *rst = RUNTIME_STATE(interp);
 
   /*fprintf(stderr, "ExitHandler\n");*/
 
@@ -23144,18 +23204,21 @@
 
   CallStackPopAll(interp);
 
-  if (RUNTIME_STATE(interp)->exitHandlerDestroyRound == NSF_EXITHANDLER_OFF) {
+  if (rst->exitHandlerDestroyRound == NSF_EXITHANDLER_OFF) {
     NsfFinalizeCmd(interp, 0);
   }
 
-  /* must be before freeing of NsfGlobalObjs */
+  /* Must be before freeing of NsfGlobalObjs */
   NsfShadowTclCommands(interp, SHADOW_UNLOAD);
 
+  MEM_COUNT_FREE("Tcl_InitHashTable", &rst->activeFilterTablePtr);
+  Tcl_DeleteHashTable(&rst->activeFilterTablePtr);
+
   /* free global objects */
   for (i = 0; i < nr_elements(NsfGlobalStrings); i++) {
     DECR_REF_COUNT(NsfGlobalObjs[i]);
   }
-  NsfStringIncrFree(&RUNTIME_STATE(interp)->iss);
+  NsfStringIncrFree(&rst->iss);
 
   /*
    * Free all data in the pointer converter
@@ -23264,6 +23327,8 @@
 Nsf_Init(Tcl_Interp *interp) {
   ClientData runtimeState;
   int result, i;
+  NsfRuntimeState *rst;
+
 #ifdef NSF_BYTECODE
   /*NsfCompEnv *interpstructions = NsfGetCompEnv();*/
 #endif
@@ -23340,39 +23405,38 @@
 #if defined(NSF_PROFILE)
   NsfProfileInit(interp);
 #endif
+  rst = RUNTIME_STATE(interp);
+  rst->doFilters = 1;
+  rst->doCheckResults = 1;
+  rst->doCheckArguments = 1;
 
-  RUNTIME_STATE(interp)->doFilters = 1;
-  RUNTIME_STATE(interp)->doCheckResults = 1;
-  RUNTIME_STATE(interp)->doCheckArguments = 1;
-
   /* create nsf namespace */
-  RUNTIME_STATE(interp)->NsfNS =
-    Tcl_CreateNamespace(interp, "::nsf", NULL, (Tcl_NamespaceDeleteProc *)NULL);
+  rst->NsfNS = Tcl_CreateNamespace(interp, "::nsf", NULL, (Tcl_NamespaceDeleteProc *)NULL);
 
   MEM_COUNT_ALLOC("TclNamespace", RUNTIME_STATE(interp)->NsfNS);
 
   /*
    * init an empty, faked proc structure in the RUNTIME state
    */
-  RUNTIME_STATE(interp)->fakeProc.iPtr = (Interp *)interp;
-  RUNTIME_STATE(interp)->fakeProc.refCount = 1;
-  RUNTIME_STATE(interp)->fakeProc.cmdPtr = NULL;
-  RUNTIME_STATE(interp)->fakeProc.bodyPtr = NULL;
-  RUNTIME_STATE(interp)->fakeProc.numArgs  = 0;
-  RUNTIME_STATE(interp)->fakeProc.numCompiledLocals = 0;
-  RUNTIME_STATE(interp)->fakeProc.firstLocalPtr = NULL;
-  RUNTIME_STATE(interp)->fakeProc.lastLocalPtr = NULL;
+  rst->fakeProc.iPtr = (Interp *)interp;
+  rst->fakeProc.refCount = 1;
+  rst->fakeProc.cmdPtr = NULL;
+  rst->fakeProc.bodyPtr = NULL;
+  rst->fakeProc.numArgs  = 0;
+  rst->fakeProc.numCompiledLocals = 0;
+  rst->fakeProc.firstLocalPtr = NULL;
+  rst->fakeProc.lastLocalPtr = NULL;
 
   /* NsfClasses in separate Namespace / Objects */
-  RUNTIME_STATE(interp)->NsfClassesNS =
+  rst->NsfClassesNS =
     Tcl_CreateNamespace(interp, "::nsf::classes", NULL,
                         (Tcl_NamespaceDeleteProc *)NULL);
   MEM_COUNT_ALLOC("TclNamespace", RUNTIME_STATE(interp)->NsfClassesNS);
 
 
   /* cache interpreters proc interpretation functions */
-  RUNTIME_STATE(interp)->objInterpProc = TclGetObjInterpProc();
-  RUNTIME_STATE(interp)->exitHandlerDestroyRound = NSF_EXITHANDLER_OFF;
+  rst->objInterpProc = TclGetObjInterpProc();
+  rst->exitHandlerDestroyRound = NSF_EXITHANDLER_OFF;
 
   RegisterExitHandlers(interp);
   NsfStringIncrInit(&RUNTIME_STATE(interp)->iss);
@@ -23384,6 +23448,9 @@
     INCR_REF_COUNT(NsfGlobalObjs[i]);
   }
 
+  Tcl_InitHashTable(&rst->activeFilterTablePtr, TCL_STRING_KEYS);
+  MEM_COUNT_ALLOC("Tcl_InitHashTable", &rst->activeFilterTablePtr);
+
   /* create namespaces for the different command types */
   Tcl_CreateNamespace(interp, "::nsf::cmd", 0, (Tcl_NamespaceDeleteProc *)NULL);
   for (i=0; i < nr_elements(method_command_namespace_names); i++) {
@@ -23396,7 +23463,7 @@
   }
 
   /*
-   * overwritten Tcl cmds
+   * shadowed Tcl cmds
    */
   result = NsfShadowTclCommands(interp, SHADOW_LOAD);
   if (result != TCL_OK) {
@@ -23424,8 +23491,7 @@
                          (Tcl_ResolveCmdProc *)InterpColonCmdResolver,
                          InterpColonVarResolver,
                          (Tcl_ResolveCompiledVarProc *)InterpCompiledColonVarResolver);
-  RUNTIME_STATE(interp)->colonCmd =
-    Tcl_FindCommand(interp, "::nsf::colon", NULL, TCL_GLOBAL_ONLY);
+  rst->colonCmd = Tcl_FindCommand(interp, "::nsf::colon", NULL, TCL_GLOBAL_ONLY);
 
   /*
    * SS: Tcl occassionally resolves a proc's cmd structure (e.g., in
@@ -23438,7 +23504,7 @@
    *  indicating "::nsf::colon" (which is sufficiently misleading and
    *  reveals internals not to be revealed ...).
   */
-  RUNTIME_STATE(interp)->fakeProc.cmdPtr = (Command *)RUNTIME_STATE(interp)->colonCmd;
+  rst->fakeProc.cmdPtr = (Command *)RUNTIME_STATE(interp)->colonCmd;
 
   {
     /*
Index: generic/nsfInt.h
===================================================================
diff -u -r120b838888f00fe1a3130bf184fd079d06d89fa6 -rb9000cff9206c8621e46524c2f12f8fc8fcb6f86
--- generic/nsfInt.h	(.../nsfInt.h)	(revision 120b838888f00fe1a3130bf184fd079d06d89fa6)
+++ generic/nsfInt.h	(.../nsfInt.h)	(revision b9000cff9206c8621e46524c2f12f8fc8fcb6f86)
@@ -783,6 +783,9 @@
   int doKeepinitcmd;
   int doProfile;
   int doSoftrecreate;
+  /* keep track of defined filters */
+  Tcl_HashTable activeFilterTablePtr;
+
   /*
    * shutdown handling
    */