Implemented more efficient garbage collectior
from worst case of O(n) -> O(1) - where n is the number of insertions in a list So this is a huge improvement, I guess :)
This commit is contained in:
		
							parent
							
								
									38bf398709
								
							
						
					
					
						commit
						39dc2317b7
					
				| @ -208,6 +208,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) { | |||||||
|         yield* this.os.iterate(this, null, null, function * (o) { |         yield* this.os.iterate(this, null, null, function * (o) { | ||||||
|           o = Y.utils.copyObject(o) |           o = Y.utils.copyObject(o) | ||||||
|           delete o.origin |           delete o.origin | ||||||
|  |           delete o.originOf | ||||||
|           db1.push(o) |           db1.push(o) | ||||||
|         }) |         }) | ||||||
|       }) |       }) | ||||||
| @ -222,6 +223,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) { | |||||||
|         yield* this.os.iterate(this, null, null, function * (o) { |         yield* this.os.iterate(this, null, null, function * (o) { | ||||||
|           o = Y.utils.copyObject(o) |           o = Y.utils.copyObject(o) | ||||||
|           delete o.origin |           delete o.origin | ||||||
|  |           delete o.originOf | ||||||
|           expect(db1[count++]).toEqual(o) |           expect(db1[count++]).toEqual(o) | ||||||
|         }) |         }) | ||||||
|       }) |       }) | ||||||
|  | |||||||
| @ -126,6 +126,19 @@ module.exports = function (Y/* :any */) { | |||||||
|       execute: function *(op) { |       execute: function *(op) { | ||||||
|         var i // loop counter
 |         var i // loop counter
 | ||||||
|         var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
 |         var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
 | ||||||
|  | 
 | ||||||
|  |         if (op.origin != null) { | ||||||
|  |           // we save in origin that op originates in it
 | ||||||
|  |           // we need that later when we eventually garbage collect origin (see transaction)
 | ||||||
|  |           var origin = yield* this.getOperation(op.origin) | ||||||
|  |           if (origin.originOf == null) { | ||||||
|  |             origin.originOf = [] | ||||||
|  |           } | ||||||
|  |           origin.originOf.push(op.id) | ||||||
|  |           yield* this.setOperation(origin) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // now we begin to insert op in the list of insertions..
 | ||||||
|         var o |         var o | ||||||
|         var parent |         var parent | ||||||
|         var start |         var start | ||||||
|  | |||||||
| @ -362,23 +362,31 @@ module.exports = function (Y/* :any */) { | |||||||
|         if (o.right != null) { |         if (o.right != null) { | ||||||
|           var right = yield* this.getOperation(o.right) |           var right = yield* this.getOperation(o.right) | ||||||
|           right.left = o.left |           right.left = o.left | ||||||
|           if (Y.utils.compareIds(right.origin, o.id)) { // rights origin is o
 | 
 | ||||||
|  |           if (Y.utils.compareIds(right.origin, id)) { // rights origin is o
 | ||||||
|             // find new origin of right ops
 |             // find new origin of right ops
 | ||||||
|             // origin is the first left deleted operation
 |             // origin is the first left deleted operation
 | ||||||
|             var neworigin = o.left |             var neworigin = o.left | ||||||
|  |             var neworigin_ = null | ||||||
|             while (neworigin != null) { |             while (neworigin != null) { | ||||||
|               var neworigin_ = yield* this.getOperation(neworigin) |               neworigin_ = yield* this.getOperation(neworigin) | ||||||
|               if (neworigin_.deleted) { |               if (neworigin_.deleted) { | ||||||
|                 break |                 break | ||||||
|               } |               } | ||||||
|               neworigin = neworigin_.left |               neworigin = neworigin_.left | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             // reset origin of all right ops (except first right - duh!),
 | ||||||
|  | 
 | ||||||
|  |             /* ** The following code does not rely on the the originOf property ** | ||||||
|  |                   I recently added originOf to all Insert Operations (see Struct.Insert.execute), | ||||||
|  |                   which saves which operations originate in a Insert operation. | ||||||
|  |                   Garbage collecting without originOf is more memory efficient, but is nearly impossible for large texts, or lists! | ||||||
|  |                   But I keep this code for now | ||||||
|  |             ``` | ||||||
|             // reset origin of right
 |             // reset origin of right
 | ||||||
|             right.origin = neworigin |             right.origin = neworigin | ||||||
| 
 |             // search until you find origin pointer to the left of o
 | ||||||
|             // reset origin of all right ops (except first right - duh!),
 |  | ||||||
|             // until you find origin pointer to the left of o
 |  | ||||||
|             if (right.right != null) { |             if (right.right != null) { | ||||||
|               var i = yield* this.getOperation(right.right) |               var i = yield* this.getOperation(right.right) | ||||||
|               var ids = [o.id, o.right] |               var ids = [o.id, o.right] | ||||||
| @ -399,10 +407,42 @@ module.exports = function (Y/* :any */) { | |||||||
|                 } |                 } | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           } /* otherwise, rights origin is to the left of o, |             ``` | ||||||
|                then there is no right op (from o), that origins in o */ |             */ | ||||||
|  |             // ** Now the new implementation starts **
 | ||||||
|  |             // reset neworigin of all originOf[*]
 | ||||||
|  |             for (var _i in o.originOf) { | ||||||
|  |               var originsIn = yield* this.getOperation(o.originOf[_i]) | ||||||
|  |               if (originsIn != null) { | ||||||
|  |                 originsIn.origin = neworigin | ||||||
|  |                 yield* this.setOperation(originsIn) | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |             if (neworigin != null) { | ||||||
|  |               if (neworigin_.originOf == null) { | ||||||
|  |                 neworigin_.originOf = o.originOf | ||||||
|  |               } else { | ||||||
|  |                 neworigin_.originOf = o.originOf.concat(neworigin_.originOf) | ||||||
|  |               } | ||||||
|  |               yield* this.setOperation(neworigin_) | ||||||
|  |             } | ||||||
|  |             // we don't need to set right here, because
 | ||||||
|  |             // right should be in o.originOf => it is set it the previous for loop
 | ||||||
|  |           } else { | ||||||
|  |             // we didn't need to reset the origin of right
 | ||||||
|  |             // so we have to set right here
 | ||||||
|             yield* this.setOperation(right) |             yield* this.setOperation(right) | ||||||
|           } |           } | ||||||
|  |           // o may originate in another operation.
 | ||||||
|  |           // Since o is deleted, we have to reset o.origin's `originOf` property
 | ||||||
|  |           if (o.origin != null) { | ||||||
|  |             var origin = yield* this.getOperation(o.origin) | ||||||
|  |             origin.originOf = origin.originOf.filter(function (_id) { | ||||||
|  |               return !Y.utils.compareIds(id, _id) | ||||||
|  |             }) | ||||||
|  |             yield* this.setOperation(origin) | ||||||
|  |           } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         if (o.parent != null) { |         if (o.parent != null) { | ||||||
|           // remove gc'd op from parent, if it exists
 |           // remove gc'd op from parent, if it exists
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user