Преглед изворни кода

ncd: optimize destruction of statements which don't do anything on destruction

ambrop7 пре 13 година
родитељ
комит
9a44cabbe9
3 измењених фајлова са 57 додато и 3 уклоњено
  1. 28 3
      ncd/NCDInterpreter.c
  2. 14 0
      ncd/NCDModule.c
  3. 15 0
      ncd/NCDModule.h

+ 28 - 3
ncd/NCDInterpreter.c

@@ -713,6 +713,7 @@ void process_work_job_handler_terminating (struct process *p)
     process_assert_pointers(p);
     ASSERT(p->state == PSTATE_TERMINATING)
     
+again:
     if (p->fp == 0) {
         NCDInterpreter *interp = p->interp;
         
@@ -742,14 +743,38 @@ void process_work_job_handler_terminating (struct process *p)
     if (ps->inst.istate != SSTATE_DYING) {
         statement_log(ps, BLOG_INFO, "killing");
         
-        // set statement state DYING
-        ps->inst.istate = SSTATE_DYING;
-        
         // update AP
         if (p->ap > ps->i) {
             p->ap = ps->i;
         }
         
+        // optimize for statements which can be destroyed immediately
+        if (NCDModuleInst_TryFree(&ps->inst)) {
+            if (BLog_WouldLog(BLOG_INFO, BLOG_CURRENT_CHANNEL)) {
+                if (ps->inst.is_error) {
+                    statement_log(ps, BLOG_ERROR, "died with error");
+                } else {
+                    statement_log(ps, BLOG_INFO, "died");
+                }
+            }
+            
+            // free arguments memory
+            NCDValMem_Free(&ps->args_mem);
+            
+            // set statement state FORGOTTEN
+            ps->inst.istate = SSTATE_FORGOTTEN;
+            
+            // update FP
+            while (p->fp > 0 && p->statements[p->fp - 1].inst.istate == SSTATE_FORGOTTEN) {
+                p->fp--;
+            }
+            
+            goto again;
+        }
+        
+        // set statement state DYING
+        ps->inst.istate = SSTATE_DYING;
+        
         // order it to die
         NCDModuleInst_Die(&ps->inst);
         return;

+ 14 - 0
ncd/NCDModule.c

@@ -125,6 +125,20 @@ void NCDModuleInst_Die (NCDModuleInst *n)
     return;
 }
 
+int NCDModuleInst_TryFree (NCDModuleInst *n)
+{
+    DebugObject_Access(&n->d_obj);
+    ASSERT(n->state == STATE_UP || n->state == STATE_DOWN_CLEAN || n->state == STATE_DOWN_UNCLEAN)
+    
+    if (n->m->func_die) {
+        return 0;
+    }
+    
+    DebugObject_Free(&n->d_obj);
+    
+    return 1;
+}
+
 void NCDModuleInst_Clean (NCDModuleInst *n)
 {
     DebugObject_Access(&n->d_obj);

+ 15 - 0
ncd/NCDModule.h

@@ -415,6 +415,21 @@ void NCDModuleInst_Free (NCDModuleInst *n);
  */
 void NCDModuleInst_Die (NCDModuleInst *n);
 
+/**
+ * Attempts to destroy the instance immediately.
+ * This function can be used to optimize destroying instances of modules which
+ * don't specify any {@link NCDModule_func_die} handler. If immediate destruction
+ * is not possible, this does nothing and returns 0; {@link NCDModuleInst_Die}
+ * should be used to destroy the instance instead. If however immediate destruction
+ * is possible, this destroys the module instance and returns 1; {@link NCDModuleInst_Free}
+ * must not be called after that.
+ * The instance must be in down or up state, as for {@link NCDModuleInst_Die}.
+ * 
+ * @param n the instance
+ * @return 1 if destruction was performed, 0 if not
+ */
+int NCDModuleInst_TryFree (NCDModuleInst *n);
+
 /**
  * Informs the module that it is in a clean state to proceed.
  * The instance must be in down state.