Performance of NativeScripts

Is it expected to have script-based sorting much slower then field-based sorting? (x4 times slower then field-based in my tests) Is there any fundamental performance problem in processing - i.e. why the limitation to one script per request?

Using the following native script for testing:

public class RealPrice extends AbstractFloatSearchScript {
	public static class Factory implements NativeScriptFactory {

        /**
         * This method is called for every search on every shard.
         *
         * @param params list of script parameters passed with the query
         * @return new native script
         */
        @Override
        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
            return new RealPrice();
        }
    }
	@Override
	public float runAsFloat() {
		Doubles price  = (Doubles)doc().get("facet_price");
		return Math.abs(10000 - price.get(0).floatValue());
	}

}

Running ~5k queries of the form for 15min:

{
  "explain": false,
  "fields": [
    "sku",
    "facet_inStock",
    
    "score"
  ],
  "from": 0,
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": {
            "term": {
              "searchable": "1"
            }
          },
          "must_not": [
            {
              "term": {
                "product_invisible": "1"
              }
            },
            {
              "terms": {
                "product_visibility": [
                  "1",
                  "3"
                ]
              }
            }
          ]
        }
      },
      "query": {
        "bool": {
          "boost": 2,
          "minimum_should_match": "1",
          "should": [
            {
              "multi_match": {
                "fields": [
                  "attributes_brand_3^2.000000",
                  "category^2.000000",
                  "name^1.500000",
                  "attributes_author_131^1.000000",
                  "keywords_field^2.500000",
                  "skus^5.000000",
                ],
                "minimum_should_match": "2<-1 5<80%",
                "query": "iphone 6 4.7 case",
                "slop": 20,
                "tie_breaker": 1,
                "type": "cross_fields",
                "use_dis_max": true
              }
            },
            {
              "multi_match": {
                "fields": [
                  "name^1.500000",
                  "category^2.000000",
                  "attributes_brand_3^2.000000",
                  "keywords_field^2.500000",
                  "attributes_author_131^1.000000",
                  "skus^5.000000",
                ],
                "operator": "AND",
                "query": "iphone 6 4.7 case",
                "slop": 20,
                "tie_breaker": 1,
                "type": "phrase",
                "use_dis_max": true
              }
            }
          ]
        }
      }
    }
  },
  "size": 20,
  "sort": {
     "_script" : {
          "type" : "number",
          "script" : {
              "lang": "native",
              "script": "real_price"
          }
      }
  }
}

Native field sorting has direct access to internal data structures. Using scripting comes with an overhead (even if it's a native script). See for example your line Doubles price = (Doubles)doc().get("facet_price"); - this involves much more than what an internal code would do. All of that said, scripting are flexible and useful. If the current speed is not acceptable and you need script, considering using more shards increase the parallelism of the search (and giving it more resources)

Interestingly I observe that performance degradation is noticeable only with scripted sorting, but not with function_score. Any ideas on what may be the cause? Posted here: