This is the sort of thing I think about while driving home...

I see databases using IP variables use a semaphore/locking scheme before
writing to the variable. Something like this:

Lock_object("objectName")
Append to array(<>myArray;$someValue)
Unlock_object("objectName")


The Lock_object method attempts to set a semaphore. If the semaphore is
already set, indicating another process is attempting to update this
variable at the same time, it waits a tick and this continues until it sets
the semaphore.

I wondered how likely it would be for the situation to arise where two
processes would be attempting to access an IP var at the same time and what
4D would do. So I wrote a little test to investigate. The methods are at
the end for anyone who cares to replicate.

The methodology is to start a process which clears an IP text array. Then I
spin off a number (I used 400) other processes. Each of these waits for the
same time (using milliseconds here) then begins a loop that writes some
identifying data to the text array. I ran the test using object locking and
without.

Overview -

There were no lost updates due to collisions in either test case
Setting the semaphore doesn't take much time, but it takes some

Without adding some delay in the drone loops each loop would complete
before the next one began

To introduce some randomness I delay each drone by 1 or 2 clicks


Limitations

The run times are approximate because the delay command waits for 1 tick,
about 17 ms

I didn't look at the effect on writing to multiple, synchronized arrays

My Takeaway - it doesn't seem like much to worry about in terms of locking
IP variables against lost data due to collisions of multiple processes
attempting to write to the same IP var at the same time. My understanding
of why is because this version of 4D is still single threaded. This is why
400 processes are running 'simultaneously' they actually are queued up by
4D and processed sequentially. This is borne out by the fact that as the
number of drones increases the run time increases proportionally in both
cases. If the un-locked version were able to proceed without a successful
write that version would be significantly faster. It's not. So the number
of drones increases the run time due to queuing regardless of setting or
not setting the semaphore.

This situation would be different in the case of multi-threaded execution -
but you can't use an IP var in that case anyway. Probably for just this
reason.

So I'm concluding the whole variable locking fetish is unnecessary.


The test consists of four methods:

Let's call this one "Test":

ARRAY TEXT(<>aTestArray;0)
  // $determine the start time
$delay:=2
$iterations:=20
$nDrones:=400

$n:=Count user processes  //  benchmark

$ms:=Milliseconds+2000  // add 2 secs to now before drones start

  // start a few other processes
For ($i;1;$nDrones)
drone ($i;$ms;$iterations)
End for

  //  wait a bit for everything to run
While ($n<Count user processes)  // some are still running
DELAY PROCESS(Current process;1)
End while

$ms:=Milliseconds-$ms  // approx elapsed time
  // examine the array
$report:="Drones: "+String($nDrones)+"\rIterations:
"+String($iterations)+"\r"
$report:=$report+"Results:\r"
$report:=$report+"Run time: ~"+String($ms)+" ms\r"
$n:=($iterations*$nDrones)-Size of array(<>aTestArray)
$report:=$report+String($n)+" Missing elements\r"
ALERT($report)


​This is the drone method:

​// drone
C_LONGINT($1;$2;$3;$4)
C_LONGINT($id;$i)
C_TEXT($procName)

Case of
: (Count parameters=3)
$procName:="drone_"+String($1)
$id:=New process(Current method name;0;$procName;$1;$2;$3;Current process)

: (Count parameters=4)  //     new process
While (Milliseconds<$2)  // wait for the starting time
DELAY PROCESS(Current process;1)
End while

  // now do the loop
For ($i;1;$3)
APPEND TO ARRAY(<>aTestArray;"Drone "+String($1)+": "+String($i)+"
 "+String(Milliseconds))
If (Milliseconds%2=0)  // introduce some variability
DELAY PROCESS(Current process;1)
Else
DELAY PROCESS(Current process;2)
End if
End for
End case

//droneWithLocking
C_LONGINT($1;$2;$3;$4)
C_LONGINT($id;$i)
C_TEXT($procName)

Case of
: (Count parameters=3)
$procName:="drone_"+String($1)
$id:=New process(Current method name;0;$procName;$1;$2;$3;Current process)

: (Count parameters=4)  //     new process
While (Milliseconds<$2)  // wait for the starting time
DELAY PROCESS(Current process;1)
End while

  // now do the loop
For ($i;1;$3)
Lock_object ("<>aTestArray")
APPEND TO ARRAY(<>aTestArray;"Drone "+String($1)+": "+String($i)+"
 "+String(Milliseconds))
Unlock_object ("<>aTestArray")

If (Milliseconds%2=0)  // introduce some variability
DELAY PROCESS(Current process;1)
Else
DELAY PROCESS(Current process;2)
End if
End for
End case


//Lock_object
While (Semaphore("$"+$1))
IDLE
End while

//Unlock_object

CLEAR SEMAPHORE("$"+$1)


-- 
Kirk Brooks
San Francisco, CA
=======================
**********************************************************************
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**********************************************************************

Reply via email to