diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 32306d8db765db812ed0f6190d3d4700bd21a375..a7bdd491046a414116491d6bd80e6f0e433cb13b 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -41,6 +41,10 @@ add_executable(bps_tree.test bps_tree.cc ${CMAKE_SOURCE_DIR}/third_party/qsort_a
 target_link_libraries(bps_tree.test small)
 add_executable(bps_tree_itr.test bps_tree_itr.cc ${CMAKE_SOURCE_DIR}/third_party/qsort_arg.c)
 target_link_libraries(bps_tree_itr.test small)
+add_executable(rtree.test rtree.cc ${CMAKE_SOURCE_DIR}/third_party/rtree.cc)
+target_link_libraries(rtree.test)
+add_executable(rtree_itr.test rtree_itr.cc ${CMAKE_SOURCE_DIR}/third_party/rtree.cc)
+target_link_libraries(rtree_itr.test)
 add_executable(matras.test matras.cc)
 target_link_libraries(matras.test small)
 add_executable(vclock.test vclock.cc test.c
diff --git a/third_party/rtree.cc b/third_party/rtree.cc
index 2308176016c2fd7627213abbbd69ee50e77fb284..5b813f80c3c7e0c3e93c72e00bbf9f5243053383 100644
--- a/third_party/rtree.cc
+++ b/third_party/rtree.cc
@@ -24,9 +24,11 @@ class R_page {
 		reinsert_list() { chain = NULL; }
 	};
 
-	R_page* insert(R_tree* tree, rectangle_t const& r, record_t obj, int level);
+	R_page* insert(R_tree* tree, rectangle_t const& r,
+		       record_t obj, int level);
 
-	bool remove(R_tree* tree, rectangle_t const& r, record_t obj, int level, reinsert_list& rlist);
+	bool remove(R_tree* tree, rectangle_t const& r, record_t obj,
+		    int level, reinsert_list& rlist);
 
 	rectangle_t cover() const;
 
@@ -91,39 +93,39 @@ void R_tree::insert(rectangle_t const& r, record_t obj)
 
 bool R_tree::remove(rectangle_t const& r, record_t obj)
 {
-	if (height != 0) {
-		R_page::reinsert_list rlist;
-		if (root->remove(this, r, obj, height, rlist)) {
-			R_page* pg = rlist.chain;
-			int level = rlist.level;
-			while (pg != NULL) {
-				for (int i = 0, n = pg->n; i < n; i++) {
-					R_page* p = root->insert(this, pg->b[i].r,
-								 pg->b[i].p, height-level);
-					if (p != NULL) {
-						/* root splitted */
-						root = new (page_alloc()) R_page(root, p);
-						height += 1;
-						n_pages += 1;
-					}
+	R_page::reinsert_list rlist;
+	if (height != 0 && root->remove(this, r, obj, height, rlist)) {
+		R_page* pg = rlist.chain;
+		int level = rlist.level;
+		while (pg != NULL) {
+			for (int i = 0, n = pg->n; i < n; i++) {
+				R_page* p = root->insert(this,
+							 pg->b[i].r,
+							 pg->b[i].p,
+							 height-level);
+				if (p != NULL) {
+					/* root splitted */
+					root = new (page_alloc()) R_page(root, p);
+					height += 1;
+					n_pages += 1;
 				}
-				level -= 1;
-				R_page* next = pg->next_reinsert_page();
-				page_free(pg);
-				n_pages -= 1;
-				pg = next;
-			}
-			if (root->n == 1 && height > 1) {
-				R_page* new_root = root->b[0].p;
-				page_free(root);
-				root = new_root;
-				height -= 1;
-				n_pages -= 1;
 			}
-			n_records -= 1;
-			update_count += 1;
-			return true;
+			level -= 1;
+			R_page* next = pg->next_reinsert_page();
+			page_free(pg);
+			n_pages -= 1;
+			pg = next;
+		}
+		if (root->n == 1 && height > 1) {
+			R_page* new_root = root->b[0].p;
+			page_free(root);
+			root = new_root;
+			height -= 1;
+			n_pages -= 1;
 		}
+		n_records -= 1;
+		update_count += 1;
+		return true;
 	}
 	return false;
 }
@@ -140,7 +142,9 @@ bool R_tree_iterator::goto_first(int sp, R_page* pg)
 		}
 	} else {
 		for (int i = 0, n = pg->n; i < n; i++) {
-			if ((r.*intr_cmp)(pg->b[i].r) && goto_first(sp+1, pg->b[i].p)) {
+			if ((r.*intr_cmp)(pg->b[i].r)
+			    && goto_first(sp+1, pg->b[i].p))
+			{
 				stack[sp].page = pg;
 				stack[sp].pos = i;
 				return true;
@@ -163,7 +167,9 @@ bool R_tree_iterator::goto_next(int sp)
 		}
 	} else {
 		for (int i = stack[sp].pos, n = pg->n; ++i < n;) {
-			if ((r.*intr_cmp)(pg->b[i].r) && goto_first(sp+1, pg->b[i].p)) {
+			if ((r.*intr_cmp)(pg->b[i].r)
+			    && goto_first(sp+1, pg->b[i].p))
+			{
 				stack[sp].page = pg;
 				stack[sp].pos = i;
 				return true;
@@ -178,16 +184,19 @@ R_tree_iterator::R_tree_iterator()
 	list = NULL;
 	free = NULL;
 	tree = NULL;
+	page_list = NULL;
+	page_pos = N_ELEMS;
 }
 
 R_tree_iterator::~R_tree_iterator()
 {
-	Neighbor *curr, *next;
-	reset();
-	for (curr = free; curr != NULL; curr = next) {
+	Neighbor_page *curr, *next;
+	for (curr = page_list; curr != NULL; curr = next) {
 		next = curr->next;
-		delete curr;
+		tree->page_free(curr);
 	}
+	page_list = NULL;
+	page_pos = N_ELEMS;
 }
 
 void R_tree_iterator::reset()
@@ -203,10 +212,22 @@ void R_tree_iterator::reset()
 }
 
 
-bool R_tree_iterator::init(R_tree const* tree, rectangle_t const& r, Spatial_search_op op)
+R_tree_iterator::Neighbor* R_tree_iterator::allocate_neighbour()
+{
+	if (page_pos >= N_ELEMS) {
+		Neighbor_page* new_page = (Neighbor_page*)tree->page_alloc();
+		new_page->next = page_list;
+		page_list = new_page;
+		page_pos = 0;
+	}
+	return &page_list->buf[page_pos++];
+}
+
+bool R_tree_iterator::init(R_tree const* tree, rectangle_t const& r,
+			   Spatial_search_op op)
 {
 	reset();
-	this->tree = tree;
+	this->tree = (R_tree*)tree;
 	this->update_count = tree->update_count;
 	this->r = r;
 	this->op = op;
@@ -248,7 +269,8 @@ bool R_tree_iterator::init(R_tree const* tree, rectangle_t const& r, Spatial_sea
 		}
 	}
 	if (tree->root && goto_first(0, tree->root)) {
-		stack[tree->height-1].pos -= 1; /* will be incremented by goto_next */
+		stack[tree->height-1].pos -= 1;
+		/* will be incremented by goto_next */
 		eof = false;
 		return true;
 	} else {
@@ -273,11 +295,13 @@ void R_tree_iterator::insert(Neighbor* node)
 	}
 }
 
-R_tree_iterator::Neighbor* R_tree_iterator::new_neighbor(void* child, area_t distance, int level)
+R_tree_iterator::Neighbor* R_tree_iterator::new_neighbor(void* child,
+							 area_t distance,
+							 int level)
 {
 	Neighbor* n = free;
 	if (n == NULL) {
-		n = new Neighbor();
+		n = allocate_neighbour();
 	} else {
 		free = n->next;
 	}
@@ -301,17 +325,19 @@ record_t R_tree_iterator::next()
 		return NULL;
 	}
 	if (op == SOP_NEIGHBOR) {
-		/* To return element in order of increasing distance from specified point,
-		 * we build sorted list of R-Tree items
-		 * (ordered by distance from specified point) starting from root page.
+		/* To return element in order of increasing distance from
+		 * specified point, we build sorted list of R-Tree items
+		 * (ordered by distance from specified point) starting from
+		 * root page.
 		 * Algorithm is the following:
 		 *
 		 * insert root R-Tree page in the sorted list
 		 * while sorted list is not empty:
 		 *      get top element from the sorted list
-		 *      if it is tree leaf (record) then return it as current element
-		 *      otherwise (R-Tree page) get siblings of this R-Tree page and
-		 *      insert them in sorted list
+		 *      if it is tree leaf (record) then return it as
+		 *      current element
+		 *      otherwise (R-Tree page)  get siblings of this R-Tree
+		 *      page and insert them in sorted list
 		 */
 		while (true) {
 			Neighbor* neighbor = list;
diff --git a/third_party/rtree.h b/third_party/rtree.h
index 9d90dbd9857b6c1337abb77002317e30f1f6025b..e390a90db35b85c0941a865cdfc005cc83ec1480 100644
--- a/third_party/rtree.h
+++ b/third_party/rtree.h
@@ -159,15 +159,29 @@ class R_tree_iterator
 		area_t    distance;
 	};
 
+	enum {
+		N_ELEMS = (RTREE_PAGE_SIZE-sizeof(Neighbor*))/ sizeof(Neighbor)
+	};
+
+	struct Neighbor_page {
+		Neighbor_page* next;
+		Neighbor buf[N_ELEMS];
+	};
+
+	Neighbor* allocate_neighbour();
+
+
 	typedef bool (rectangle_t::*comparator_t)(rectangle_t const& r) const;
 
 	rectangle_t r;
 	Spatial_search_op op;
-	R_tree const* tree;
+	R_tree* tree;
 	Neighbor* list;
 	Neighbor* free;
 	bool eof;
 	int update_count;
+	Neighbor_page* page_list;
+	int page_pos;
 
 	comparator_t intr_cmp;
 	comparator_t leaf_cmp;
@@ -194,6 +208,7 @@ class R_tree
 
 	typedef void* (*page_alloc_t)();
 	typedef void (*page_free_t)(void*);
+
 public:
 	size_t used_size() const {
 		return n_pages * RTREE_PAGE_SIZE;