diff --git src/wp-includes/post.php src/wp-includes/post.php
index 88c5802..20bbf6c 100644
--- src/wp-includes/post.php
+++ src/wp-includes/post.php
@@ -4311,6 +4311,9 @@ function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' )
  * children for the same to retrieve all children of a page. Does not make any
  * SQL queries to get the children.
  *
+ * It uses auxiliary structure to hold parent-children relationships and
+ * runs in O(N) complexity
+ *
  * @since 1.5.1
  *
  * @param int   $page_id    Page ID.
@@ -4318,17 +4321,28 @@ function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' )
  * @return array List of page children.
  */
 function get_page_children( $page_id, $pages ) {
-	$page_list = array();
-	foreach ( (array) $pages as $page ) {
-		if ( $page->post_parent == $page_id ) {
-			$page_list[] = $page;
-			if ( $children = get_page_children( $page->ID, $pages ) ) {
-				$page_list = array_merge( $page_list, $children );
+	// build a hash of ID -> children
+	$children = array();
+	foreach ( (array) $pages as $p ) {
+		$children[ intval( $p->post_parent ) ][] = $p;
+	}
+
+	$post_list = array();
+	if( array_key_exists( $page_id, $children ) ) {
+		$to_look = array_reverse( $children[ $page_id ] );
+		// while we still have posts to_look add them to the list
+		while ( $to_look ) {
+			$p = array_pop( $to_look );
+			$post_list[] = $p;
+			if ( array_key_exists( $p->ID, $children ) ) {
+				foreach ( array_reverse( $children[ $p->ID ] ) as $child ) {
+					$to_look[] = $child;
+				}
 			}
 		}
 	}
 
-	return $page_list;
+	return $post_list;
 }
 
 /**
diff --git tests/phpunit/tests/post/getPageChildren.php tests/phpunit/tests/post/getPageChildren.php
new file mode 100644
index 0000000..949c854
--- /dev/null
+++ tests/phpunit/tests/post/getPageChildren.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @group post
+ */
+
+class Tests_Post_getPageChildren extends WP_UnitTestCase {
+	function setUp() {
+		parent::setUp();
+	}
+
+	function test_get_hierarchical_ordering() {
+        $page_1 = $this->factory->post->create( array( 'post_type' => 'page' ) );
+        $page_2 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_1 ) );
+        $page_3 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_1 ) );
+        $page_4 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_2 ) );
+
+        /*
+         * Here's the tree we are testing:
+         *
+         * page 1
+         * - page 2
+         * -- page 4
+         * - page 3
+         *
+         * If hierarchical => true works, the order will be 1,2,4,3.
+         * If it doesn't, they will be in the creation order, 1,2,3,4.
+         */
+
+        $pages = get_pages();
+
+        $ordered_pages = get_page_children( 0, $pages );
+        $this->assertEqualSets( array($page_1, $page_2, $page_4, $page_3 ), wp_list_pluck( $ordered_pages, 'ID' ) );
+        $ordered_pages = get_page_children( $page_1, $pages );
+        $this->assertEqualSets( array($page_2, $page_4, $page_3 ), wp_list_pluck( $ordered_pages, 'ID' ) );
+        $ordered_pages = get_page_children( $page_2, $pages );
+        $this->assertEqualSets( array( $page_4 ), wp_list_pluck( $ordered_pages, 'ID' ) );
+        $ordered_pages = get_page_children( $page_4, $pages );
+        $this->assertEqualSets( array(), wp_list_pluck( $ordered_pages, 'ID' ) );
+	}
+
+    function test_get_missing_parent() {
+        $page_1 = $this->factory->post->create( array( 'post_type' => 'page' ) );
+        $page_2 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_1 ) );
+        $page_3 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_1 ) );
+        $page_4 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_2 ) );
+
+        $pages = get_pages();
+
+        $ordered_pages = get_page_children( -1, $pages );
+        $this->assertEqualSets( array(), $ordered_pages );
+
+    }
+
+    function test_get_outside_parent() {
+        $page_1 = $this->factory->post->create( array( 'post_type' => 'page' ) );
+        $page_2 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_1 ) );
+        $page_3 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_1 ) );
+        $page_4 = $this->factory->post->create( array( 'post_type' => 'page', 'post_parent' => $page_2 ) );
+
+        $pages = get_posts( array( $page_2, $page_4 ) );
+
+        $ordered_pages = get_page_children($page_3, $pages );
+        $this->assertEqualSets( array(), $ordered_pages );
+    }
+}
