Boa constrictor domestica a Graal VM



Últimamente han sucedido muchas cosas interesantes en el mundo de Java. Uno de esos eventos fue el lanzamiento de la primera versión lista para producción de Graal VM.



Personalmente, Graal ha sido durante mucho tiempo una fuente de interés evidente para mí, y sigo de cerca los informes y las últimas noticias en esta área. En un momento, vi un informe de Chris Talinger. En él, Chris habla sobre cómo Twitter logró obtener ganancias de rendimiento significativas mediante el uso de algoritmos de aprendizaje automático para ajustar Graal. Tenía un fuerte deseo de probar algo así yo mismo. En este artículo quiero compartir lo que pasó al final.  



Experimentar



Para implementar el experimento, necesitaba:



  1. Fresh Graal VM Community Edition. En el momento de escribir este artículo, es 20.2.0
  2. entorno de nube dedicado para pruebas de carga
  3. NewRelic para recopilar métricas
  4. generador de carga de prueba
  5. un programa Python y un conjunto de scripts para implementar el algoritmo ML en sí


,



UNA=(una1,una2,......,unanorte)

F(X1,X2,......,Xnorte) .



:



F=1/metromiunanorte(CPAGUUtyolyozunatyoonorte)



, .

, :



-Dgraal.MaximumInliningSize -Dgraal.TrivialInliningSize  -Dgraal.SmallCompiledLowLevelGraphSize


. ,

.



.

:



  1. JVM


.





Twitter . .



,

. , .



NewRelic



NewRelic REST API APP_ID API_KEY.

APP_ID — . APM.

API_KEY NewRelic.



:



{
  "metric_data": {
    "from": "time",
    "to": "time",
    "metrics_not_found": "string",
    "metrics_found": "string",
    "metrics": [
      {
        "name": "string",
        "timeslices": [
          {
            "from": "time",
            "to": "time",
            "values": "hash"
          }
        ]
      }
    ]
  }
}


:



def request_metrics(params):
    app_id = "APP_ID"
    url = "https://api.newrelic.com/v2/applications/"+ app_id + "/metrics/data.json"
    headers = {'X-Api-Key':"API_KEY"}
    response = requests.get(url, headers=headers, params=params)
    return response.json()


CPU Utilzation params :



params = {
    'names[]': "CPU/User/Utilization",
    'values[]': "percent",
    'from': timerange[0],
    'to': timerange[1],
    'raw': "false"
}


timerange .





def get_timeslices(response_json, value_name):
    metrics = response_json['metric_data']['metrics'][0]
    timeslices = metrics['timeslices']
    values = []
    for t in timeslices:
        values.append(t['values'][value_name])
    return values




— .



BayesianOptimization.



.



def objective_function(maximumInliningSize, trivialInliningSize, smallCompiledLowLevelGraphSize):
    update_config(int(maximumInliningSize), int(trivialInliningSize), int(smallCompiledLowLevelGraphSize))
    timerange = do_test()
    data = get_results(timerange)
    return calculate(data)


_updateconfig , . _dotest .



JVM . , .



calculate :



    value = 1 / (mean(filtered_data))




pbounds = {
            'maximumInliningSize': (200, 500),
           'trivialInliningSize': (10, 25),
           'smallCompiledLowLevelGraphSize': (200, 650)
           }


,



  optimizer.probe(
        params={"maximumInliningSize": 300.0,
                "trivialInliningSize": 10.0,
                "smallCompiledLowLevelGraphSize": 300.0},
        lazy=True,
        )




def autotune():
    pbounds = {
                'maximumInliningSize': (200, 500),
               'trivialInliningSize': (10, 25),
               'smallCompiledLowLevelGraphSize': (200, 650)
               }

    optimizer = BayesianOptimization(
        f=objective_function,
        pbounds=pbounds,
        random_state=1,
    )

    optimizer.probe(
    params={"maximumInliningSize": 300.0,
            "trivialInliningSize": 10.0,
            "smallCompiledLowLevelGraphSize": 300.0},
    lazy=True,
    )

    optimizer.maximize(
        init_points=2,
        n_iter=10,
    )

    print(optimizer.max)


_objectivefunction 12

, . , .



:



for i, res in enumerate(optimizer.res):
    print("Iteration {}: \n\t{}".format(i, res))


.



Iteration 0:
    {'target': 0.02612330198537095, 'params': {'maximumInliningSize': 300.0, 'smallCompiledLowLevelGraphSize': 300.0, 'trivialInliningSize': 10.0}}
Iteration 1:
    {'target': 0.02666666666666667, 'params': {'maximumInliningSize': 325.1066014107722, 'smallCompiledLowLevelGraphSize': 524.1460220489712, 'trivialInliningSize': 10.001715622260173}}
...




.



, CPU Utilization Graal





:





.







CPU 4-5%.



CPU , proof of concept

.



2 Java Graal 2 . Graal JVM , Scala Kotlin.




All Articles