diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index a754d9f568..7e580e2c66 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -1323,7 +1323,7 @@ func TestLoadtx(t *testing.T) { e.runProg(t, "loadtx "+tx.Hash().StringLE(), // hash LE "run", - "loadtx --gas 10000 "+tx.Hash().StringLE(), // with GAS + "loadtx --gas 100 "+tx.Hash().StringLE(), // with GAS "run", "loadtx 0x"+tx.Hash().StringLE(), // hash LE with 0x prefix "run", diff --git a/go.mod b/go.mod index 2f2b9f8352..36f2446a4d 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( golang.org/x/term v0.35.0 golang.org/x/text v0.29.0 golang.org/x/tools v0.37.0 + gonum.org/v1/gonum v0.16.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/opcodefee/append.ipynb b/opcodefee/append.ipynb new file mode 100644 index 0000000000..e1e597ce1f --- /dev/null +++ b/opcodefee/append.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/APPEND.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"appendtype\"] == \"Array\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"appendtype\"] == \"Struct\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/cat.ipynb b/opcodefee/cat.ipynb new file mode 100644 index 0000000000..6d97e69526 --- /dev/null +++ b/opcodefee/cat.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/CAT.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"numbytes\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/clear.ipynb b/opcodefee/clear.ipynb new file mode 100644 index 0000000000..5d9cb8dcc8 --- /dev/null +++ b/opcodefee/clear.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/CLEAR.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"stacksize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/clearitems.ipynb b/opcodefee/clearitems.ipynb new file mode 100644 index 0000000000..93b5537353 --- /dev/null +++ b/opcodefee/clearitems.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/CLEARITEMS.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"numitems\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Array\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Map\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/convert.ipynb b/opcodefee/convert.ipynb new file mode 100644 index 0000000000..a9f79010f3 --- /dev/null +++ b/opcodefee/convert.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/CONVERT.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"itemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.25, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"fromtype\"] == \"Array\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"fromtype\"] == \"ByteString\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/drop.ipynb b/opcodefee/drop.ipynb new file mode 100644 index 0000000000..681f45c1a5 --- /dev/null +++ b/opcodefee/drop.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/DROP.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/dup.ipynb b/opcodefee/dup.ipynb new file mode 100644 index 0000000000..c41c6f49d8 --- /dev/null +++ b/opcodefee/dup.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/DUP.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"numbytes\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/haskey.ipynb b/opcodefee/haskey.ipynb new file mode 100644 index 0000000000..3e201bdb24 --- /dev/null +++ b/opcodefee/haskey.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/HASKEY.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"keytype\"] == \"Integer\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"keytype\"] == \"ByteString\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/initslot.ipynb b/opcodefee/initslot.ipynb new file mode 100644 index 0000000000..02b089a7f3 --- /dev/null +++ b/opcodefee/initslot.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/INITSLOT.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"localslots\", \"argslots\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/initsslot.ipynb b/opcodefee/initsslot.ipynb new file mode 100644 index 0000000000..6754918c57 --- /dev/null +++ b/opcodefee/initsslot.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/INITSSLOT.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"staticslots\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/keys.ipynb b/opcodefee/keys.ipynb new file mode 100644 index 0000000000..dd937017f6 --- /dev/null +++ b/opcodefee/keys.ipynb @@ -0,0 +1,170 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/KEYS.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxYAAAHqCAYAAACZcdjsAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAUDNJREFUeJzt3XtYlHX+//HXgMB44mTBQJKyHTwkaupmqJUlguZatGZZalaWZVIedrUs81hr2TcPlWmHLbdVS91vuWqKznrIVMJESdE0+0a5qw5UCOMhDsL9+6Mf9zohBt7EDPp8XJfX1Xzu9z285/bdLq/mPtgMwzAEAAAAABb4ebsBAAAAAHUfwQIAAACAZQQLAAAAAJYRLAAAAABYRrAAAAAAYBnBAgAAAIBlBAsAAAAAlhEsAAAAAFhGsAAAAABgGcECAFDnde/eXd27d/d2G5Vq3ry57r//fm+3AQC/KYIFAAAAAMvqebsBAAAudAcOHJCfH/8tD8CFjWABAMBvLCgoyNstAMBvjv98AgAXqMmTJ8tms+nrr7/W/fffr9DQUIWEhOiBBx7QqVOnPGqdTqe6deum0NBQNWrUSC1atNDTTz99zvdv06aNbr755grrZWVluuyyy3TnnXeaax988IE6duyoxo0bKzg4WHFxcZozZ86vfoaysjLNnj1b11xzjex2uyIjI/XII4/o2LFjv7pvUVGRJk2apCuvvFJBQUGKiYnRuHHjVFRU5FFns9mUkpKiZcuWqXXr1qpfv77i4+O1Z88eSdIbb7yhK6+8Una7Xd27d9e3337rsf/BgwfVr18/ORwO2e12NW3aVAMGDFBBQYFZ88trLGw2W6V/znz//fv3684771R4eLjsdrs6deqkFStW/OpnBwBv4BsLALjA3XXXXYqNjdX06dO1c+dOvf3224qIiNCLL74oSdq7d6/+8Ic/qG3btpo6daqCgoL09ddfa+vWred837vvvluTJ0+Wy+WSw+Ew17ds2aIjR45owIABkn4OLffcc4969Ohh/swvv/xSW7du1ciRI8/5Mx555BEtWLBADzzwgJ544gllZ2frtdde065du7R161YFBAScdb+ysjLddttt2rJli4YNG6ZWrVppz549mjVrlr766istX77co/7TTz/VihUrNGLECEnS9OnT9Yc//EHjxo3T66+/rscee0zHjh3TjBkz9OCDD2rDhg2SpOLiYiUlJamoqEiPP/64HA6HDh8+rFWrVik/P18hISFn7e/vf/97hbUJEyYoNzdXjRo1kvTz30vXrl112WWX6amnnlLDhg21dOlSJScn63//9391xx13nPPYAUCtMwAAF6RJkyYZkowHH3zQY/2OO+4wmjRpYr6eNWuWIcn4/vvvq/X+Bw4cMCQZr776qsf6Y489ZjRq1Mg4deqUYRiGMXLkSCM4ONg4ffp0td7/008/NSQZixYt8lhPTU2tsH7TTTcZN910k/n673//u+Hn52d8+umnHvvOnz/fkGRs3brVXJNkBAUFGdnZ2ebaG2+8YUgyHA6H4Xa7zfXx48cbkszaXbt2GZKMZcuWnfOzNGvWzBgyZEil22fMmGFIMt577z1zrUePHkZcXJxRWFhorpWVlRldunQxrrrqqnP+PADwBk6FAoAL3KOPPurx+oYbbtCPP/4ot9stSQoNDZUk/fOf/1RZWVmV3/fqq69W+/bttWTJEnOttLRU//jHP9S3b1/Vr1/ffP+TJ0/K6XRWq+9ly5YpJCREPXv21A8//GD+6dixoxo1aqSNGzeec99WrVqpZcuWHvvecsstklRh3x49eqh58+bm686dO0uS+vXrp8aNG1dY/+abbyTJ/EZi7dq1FU4vq6qNGzdq/PjxevzxxzV48GBJUl5enjZs2KC77rpLx48fN/v/8ccflZSUpIMHD+rw4cPn9fMA4LdCsACAC9zll1/u8TosLEySzOsU7r77bnXt2lUPPfSQIiMjNWDAAC1durRKIePuu+/W1q1bzV9yN23apNzcXN19991mzWOPPaarr75avXv3VtOmTfXggw8qNTX1V9/74MGDKigoUEREhC699FKPPydOnFBubu459927d2+F/a6++mpJqrDvL49ReWCIiYk563r5sYuNjdWYMWP09ttv65JLLlFSUpLmzp3rcX3FufznP/8xj//MmTPN9a+//lqGYejZZ5+t8BkmTZp01s8AAN7GNRYAcIHz9/c/67phGJKk+vXra/Pmzdq4caM+/vhjpaamasmSJbrlllu0bt26SveXfg4W48eP17JlyzRq1CgtXbpUISEh6tWrl1kTERGhzMxMrV27VmvWrNGaNWv07rvv6r777tPf/va3St+7rKxMERERWrRo0Vm3X3rppefcNy4uzuOX9TP9MjBU9hl/7dhJ0ssvv6z7779f//znP7Vu3To98cQTmj59uj777DM1bdq00h6Li4t15513KigoSEuXLlW9ev/9v+TyUPfnP/9ZSUlJZ93/yiuvrPS9AcAbCBYAAPn5+alHjx7q0aOHZs6cqb/85S965plntHHjRiUkJFS6X2xsrK677jotWbJEKSkp+vDDD5WcnFzh9qqBgYHq27ev+vbtq7KyMj322GN644039Oyzz1b6C/IVV1yhf/3rX+ratat5WlVVXXHFFfriiy/Uo0cP2Wy2au17PuLi4hQXF6cJEyZo27Zt6tq1q+bPn6/nnnuu0n2eeOIJZWZmavPmzYqMjPTY9rvf/U6SFBAQcM7jDwC+hFOhAOAil5eXV2Gtffv2klTh1qxnc/fdd+uzzz7TO++8ox9++MHjNChJ+vHHHz1e+/n5qW3btr/6/nfddZdKS0s1bdq0CttOnz6t/Pz8c+57+PBhvfXWWxW2/fTTTzp58uS5PlKVud1unT592mMtLi5Ofn5+5/xs7777rt544w3NnTtX1113XYXtERER6t69u9544w0dPXq0wvbvv//eevMAUMP4xgIALnJTp07V5s2b1adPHzVr1ky5ubl6/fXX1bRpU3Xr1u1X97/rrrv05z//WX/+858VHh5e4b+wP/TQQ8rLy9Mtt9yipk2b6rvvvtOrr76q9u3bq1WrVpW+70033aRHHnlE06dPV2ZmphITExUQEKCDBw9q2bJlmjNnjsezMs40ePBgLV26VI8++qg2btyorl27qrS0VPv379fSpUu1du1aderUqXoH6iw2bNiglJQU9e/fX1dffbVOnz6tv//97/L391e/fv3Ous8PP/ygxx57TK1bt1ZQUJAWLlzosf2OO+5Qw4YNNXfuXHXr1k1xcXF6+OGH9bvf/U45OTlKS0vTf/7zH33xxReW+weAmkSwAICL3G233aZvv/3W/Mbhkksu0U033aQpU6ZU+hyGMzVt2lRdunTR1q1b9dBDD1V4tsSgQYP05ptv6vXXX1d+fr4cDof5DAw/v3N/cT5//nx17NhRb7zxhp5++mnVq1dPzZs316BBg9S1a9dK9/Pz89Py5cs1a9Ysvffee/roo4/UoEED/e53v9PIkSPNi7itateunZKSkrRy5UodPnxYDRo0ULt27bRmzRpdf/31Z93nxIkTKiws1L59+8y7QJ0pOztb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qVGjRik6OlpDhgzxdnu/avr06ZoyZUqF9XXr1qlBgwZe6OjC4nQ6vd0C6hDmBVXFrKA6mBdUR12cl1OnTlW51qeDxdixY/XUU09pwIABkqS4uDh99913mj59uoYMGSKHwyFJysnJUVRUlLlfTk6O2rdvL0lyOBzKzc31eN/Tp08rLy/P3N/hcCgnJ8ejpvz1r9WUbz+b8ePHa8yYMeZrt9utmJgYJSYmKjg4uMrHAZ5KSkrkdDrVs2dPBQQEeLsd+DjmBVXFrKA6mBdUR12el/IzbqrCp4PFqVOn5OfneRmIv7+/ysrKJEmxsbFyOBxav369GSTcbrfS09M1fPhwSVJ8fLzy8/OVkZGhjh07SpI2bNigsrIyde7c2ax55plnVFJSYv5lO51OtWjRQmFhYWbN+vXrNWrUKLMXp9Op+Pj4SvsPCgpSUFBQhfWAgIA6N1S+iOOI6mBeUFXMCqqDeUF11MV5qU6/Pn3xdt++ffX888/r448/1rfffquPPvpIM2fO1B133CFJstlsGjVqlJ577jmtWLFCe/bs0X333afo6GglJydLklq1aqVevXrp4Ycf1vbt27V161alpKRowIABio6OliTde++9CgwM1NChQ7V3714tWbJEc+bM8fi2YeTIkUpNTdXLL7+s/fv3a/LkydqxY4dSUlJq/bgAAAAAvsanv7F49dVX9eyzz+qxxx5Tbm6uoqOj9cgjj2jixIlmzbhx43Ty5EkNGzZM+fn56tatm1JTU2W3282aRYsWKSUlRT169JCfn5/69eunV155xdweEhKidevWacSIEerYsaMuueQSTZw40eNZF126dNHixYs1YcIEPf3007rqqqu0fPlytWnTpnYOBgAAAODDaiRYlJaWas+ePWrWrJl56lBNaNy4sWbPnq3Zs2dXWmOz2TR16lRNnTq10prw8HAtXrz4nD+rbdu2+vTTT89Z079/f/Xv3/+cNQAAAMDF6LxOhRo1apT++te/Svo5VNx0003q0KGDYmJitGnTpprsDwAAAEAdcF7B4h//+IfatWsnSVq5cqWys7O1f/9+jR49Ws8880yNNggAAADA951XsPjhhx/M26yuXr1a/fv319VXX60HH3xQe/bsqdEGAQAAAPi+8woWkZGR2rdvn0pLS5WamqqePXtK+vn2sP7+/jXaIAAAAADfd14Xbz/wwAO66667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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 122.89135174 19509.58902616]\n", + "0.7796385292969359\n" + ] + } + ], + "source": [ + "beta, r2 = myfunc(df[df[\"keytype\"] == \"Integer\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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9/hjx06SXnjhBf3617/W3/72N23cuFETJkxQRkaGPvroI7Vs2fKCPZaVlenuu+9WUFCQVq1apQYN/vuf5KpQ95vf/EbJyck1Pv7aa6+94HMDgCcQLAAA8vPzU//+/dW/f3+9+OKL+u1vf6snnnhCW7ZsUWJi4gUfFxsbqx49emjlypVKT0/XX//6V6WkpFS7vGpgYKAGDx6swYMHq7KyUg8//LBeffVVPfnkkxf8gHzNNdfo73//u3r37m2eVlVb11xzjT755BP1799fNpvNrcdeivj4eMXHx2vGjBnauXOnevfuraVLl+rpp5++4GMmTJig3Nxcbdu2TZGRkS77fvazn0mSAgICLnr8AcCbcCoUAFzhCgsLq6116dJFkqpdmrUmQ4cO1UcffaTf//73+vbbb11Og5Kk//znPy7bfn5+6tSp048+/z333KOKigo99dRT1fadO3dORUVFF33s119/rd/97nfV9n333Xc6c+bMxd5SrTmdTp07d85lLT4+Xn5+fhd9b2+88YZeffVVLV68WD169Ki2PyIiQv369dOrr76qEydOVNv/zTffWG8eAOoY31gAwBVu7ty52rZtmwYNGqTWrVuroKBAr7zyilq2bKk+ffr86OPvuece/eY3v9FvfvMbhYeHV/t/2MeOHavCwkLdeuutatmypb766iu99NJL6tKlizp06HDB5+3bt68efPBBZWRkKDc3V0lJSQoICNDRo0e1evVqLVy40OVeGecbOXKkVq1apYceekhbtmxR7969VVFRoc8++0yrVq3S+++/r+7du7t3oGqwefNmpaena8iQIWrbtq3OnTunP/7xj/L391dqamqNj/n222/18MMPKy4uTkFBQXrrrbdc9t95551q3LixFi9erD59+ig+Pl4PPPCAfvaznyk/P1/Z2dn697//rU8++cRy/wBQlwgWAHCFu/322/Xll1+a3zi0aNFCffv21Zw5cy54H4bztWzZUr169dKOHTs0duzYaveWGDFihF577TW98sorKioqkt1uN++B4ed38S/Oly5dqm7duunVV1/V448/rgYNGqhNmzYaMWKEevfufcHH+fn5ac2aNZo/f77efPNNvfPOO2rUqJF+9rOfaeLEieaPuK3q3LmzkpOTtXbtWn399ddq1KiROnfurPfee0833nhjjY85ffq0SkpKdPjwYfMqUOfL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9cADD2j37t3asWOH0tPTNWzYMEVHR0uSfvWrXykwMFBjxozRoUOHtHLlSi1cuNDlNKaJEycqMzNTL7zwgj777DPNnj1be/bsUXp6er0fFwAAAMDbePWpUC+99JKefPJJPfzwwyooKFB0dLQefPBBzZw506yZNm2azpw5o3HjxqmoqEh9+vRRZmamgoP/e1nK5cuXKz09Xf3795efn59SU1O1aNEic39oaKg2btyotLQ0devWTS1atNDMmTNd7nXRq1cvrVixQjNmzNDjjz+u6667TmvWrFHHjh3r52AAAAAAXsyrg0XTpk21YMECLViw4II1NptNc+fO1dy5cy9YEx4erhUrVlz0tTp16qQPP/zwojVDhgzRkCFDLloDAAAAXIm8+lQoAAAAAL6BYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALDM64PF119/rREjRqh58+Zq2LCh4uPjtWfPHnO/YRiaOXOmoqKi1LBhQyUmJuro0aMuz1FYWKjhw4crJCREYWFhGjNmjE6fPu1Ss3//ft10000KDg5WTEyM5s2bV62X1atXq3379goODlZ8fLw2bNjw07xpAAAAwMd4dbA4efKkevfurYCAAL333ns6fPiwXnjhBTVr1sysmTdvnhYtWqSlS5dq165daty4sZKTk1VSUmLWDB8+XIcOHVJWVpbWrVunbdu2ady4ceZ+p9OppKQktW7dWjk5OXr++ec1e/Zsvfbaa2bNzp07de+992rMmDHat2+fUlJSlJKSooMHD9bPwQAAAAC8WANPN3Axzz33nGJiYvTGG2+Ya7GxseY/G4ahBQsWaMaMGbrjjjskSW+++aYiIyO1Zs0aDRs2TJ9++qkyMzP18ccfq3v37pKkl156Sb/4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aGiop1sBgMtGA083AABAfQsMDJTdbvd0GwBwWeEbCwBAnausrFRGRoZiY2PVsGFDde7cWX/+858vWL99+3bddNNNatiwoWJiYjRhwgSdOXPG3N+mTRs9/fTTuu+++9SkSRO1bt1a7777rr755hvdcccdatKkiTp16qQ9e/aYj/nqq680ePBgNWvWTI0bN9b111+vDRs2SKp+KlS/fv1ks9mq/fnyyy8lSUVFRRo7dqyuuuoqhYSE6NZbb9Unn3xS9wcOAHwYwQIAUOcyMjL05ptvaunSpTp06JAmT56sESNG6IMPPqhW+49//EMDBw5Uamqq9u/fr5UrV2r79u1KT093qZs/f7569+6tffv2adCgQRo5cqTuu+8+jRgxQnv37tU111yj++67T4ZhSJLS0tJUWlqqbdu26cCBA3ruuefUpEmTGvv961//qhMnTph/7rrrLrVr106RkZGSpCFDhqigoEDvvfeecnJy1LVrV/Xv31+FhYV1fOQAwHfZjKr/BQYAoA6UlpYqPDxcf//735WQkGCujx07VmfPntW4ceN0yy236OTJkwoLC9PYsWPl7++vV1991azdvn27+vbtqzNnzig4OFht2rTRTTfdpD/+8Y+SJIfDoaioKD355JOaO3euJOmjjz5SQkKCTpw4Ibvdrk6dOik1NVWzZs2q1uPWrVtdejjf/PnzNXfuXO3atUtt27bV9u3bNWjQIBUUFCgoKMisu/baazVt2jSNGzeuLg8fAPgsfmMBAKhTX3zxhc6ePasBAwa4rJeVlemGG26oVv/JJ59o//79Wr58ublmGIYqKyuVl5enDh06SJI6depk7q/6JiE+Pr7aWkFBgex2uyZMmKDx48dr48aNSkxMVGpqqstz1OS9997TY489prVr16pt27Zmf6dPn1bz5s1dar/77jv94x//+NHjAQBXCoIFAKBOnT59WpK0fv16XX311S77goKCqn0YP336tB588EFNmDCh2nO1atXK/OeAgADzn2022wXXKisrJX3/DUlycrLWr1+vjRs3KiMjQy+88IIeeeSRGvs+fPiwhg0bpmeffVZJSUku/UVFRWnr1q3VHvPDbzsA4EpGsAAA1Km4uDgFBQXp2LFj6tu3b7X9PwwWXbt21eHDh3XttdfWeS8xMTF66KGH9NBDD2n69On63e9+V2Ow+PbbbzV48GClpqZq8uTJ1fpzOBxq0KCB2rRpU+c9AsDlgmABAKhTTZs21W9+8xtNnjxZlZWV6tOnj4qLi7Vjxw6FhISodevWLvWPPvqobrzxRqWnp2vs2LFq3LixDh8+rKysLL388suX3MekSZN02223qW3btjp58qS2bNlinlb1Q6mpqWrUqJFmz54th8Nhrl911VVKTExUQkKCUlJSNG/ePLVt21bHjx/X+vXrdeedd6p79+6X3CMAXE4IFgCAOvfUU0/pqquuUkZGhv75z38qLCxMXbt21eOPP26eqlSlU6dO+uCDD/TEE0/opptukmEYuuaaazR06FBLPVRUVCgtLU3//ve/FRISooEDB2r+/Pk11m7btk2SqoWevLw8tWnTRhs2bNATTzyh0aNH65tvvpHdbtfNN99s/q4DAMBVoQAAAADUAe5jAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALCNYAAAAALCMYAEAAADAMoIFAAAAAMsIFgAAAAAsI1gAAAAAsOz/ATVuunf6d9LvAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 129.68313953 37481.49709302]\n", + "0.602234093211876\n" + ] + } + ], + "source": [ + "beta, r2 = myfunc(df[df[\"keytype\"] == \"ByteString\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/memcpy.ipynb b/opcodefee/memcpy.ipynb new file mode 100644 index 0000000000..897b63a84b --- /dev/null +++ b/opcodefee/memcpy.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/MEMCPY.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"numbytes\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/newarrayt.ipynb b/opcodefee/newarrayt.ipynb new file mode 100644 index 0000000000..658c87daa2 --- /dev/null +++ b/opcodefee/newarrayt.ipynb @@ -0,0 +1,154 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/NEWARRAYT.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"arraytype\"] == \"Boolean\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"arraytype\"] == \"Integer\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"arraytype\"] == \"ByteString\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"arraytype\"] == \"Any\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/newbuffer.ipynb b/opcodefee/newbuffer.ipynb new file mode 100644 index 0000000000..7d2432c31b --- /dev/null +++ b/opcodefee/newbuffer.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/NEWBUFFER.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"numbytes\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/opcode_results/APPEND.csv b/opcodefee/opcode_results/APPEND.csv new file mode 100644 index 0000000000..6fad885bbd --- /dev/null +++ b/opcodefee/opcode_results/APPEND.csv @@ -0,0 +1,17 @@ +opcode,elemtype,appendtype,refcount,numiters,ns +APPEND,Array,Array,255,100000,3643 +APPEND,Array,Array,511,100000,6570 +APPEND,Array,Array,767,100000,9487 +APPEND,Array,Array,1023,100000,12304 +APPEND,Array,Array,1279,100000,15208 +APPEND,Array,Array,1535,100000,17981 +APPEND,Array,Array,1791,100000,21290 +APPEND,Array,Array,2047,100000,24487 +APPEND,Array,Struct,255,100000,31951 +APPEND,Array,Struct,511,100000,60733 +APPEND,Array,Struct,767,100000,82752 +APPEND,Array,Struct,1023,100000,113556 +APPEND,Array,Struct,1279,100000,125047 +APPEND,Array,Struct,1535,100000,147812 +APPEND,Array,Struct,1791,100000,174061 +APPEND,Array,Struct,2047,100000,197509 diff --git a/opcodefee/opcode_results/CAT.csv b/opcodefee/opcode_results/CAT.csv new file mode 100644 index 0000000000..419bb97fe0 --- /dev/null +++ b/opcodefee/opcode_results/CAT.csv @@ -0,0 +1,9 @@ +opcode,numbytes,numiters,ns +CAT,16383,100000,3001 +CAT,32766,100000,4989 +CAT,49149,100000,7379 +CAT,65532,100000,9404 +CAT,81915,100000,11330 +CAT,98298,100000,13577 +CAT,114681,100000,16063 +CAT,131064,100000,18141 diff --git a/opcodefee/opcode_results/CLEAR.csv b/opcodefee/opcode_results/CLEAR.csv new file mode 100644 index 0000000000..43babc8e70 --- /dev/null +++ b/opcodefee/opcode_results/CLEAR.csv @@ -0,0 +1,17 @@ +opcode,refcount,stacksize,numiters,ns +CLEAR,256,1,100000,1789 +CLEAR,512,1,100000,3209 +CLEAR,768,1,100000,4609 +CLEAR,1024,1,100000,5840 +CLEAR,1280,1,100000,7212 +CLEAR,1536,1,100000,8809 +CLEAR,1792,1,100000,10395 +CLEAR,2048,1,100000,12335 +CLEAR,256,256,100000,1639 +CLEAR,512,512,100000,2974 +CLEAR,768,768,100000,4214 +CLEAR,1024,1024,100000,5461 +CLEAR,1280,1280,100000,6595 +CLEAR,1536,1536,100000,7850 +CLEAR,1792,1792,100000,9222 +CLEAR,2048,2048,100000,10282 diff --git a/opcodefee/opcode_results/CLEARITEMS.csv b/opcodefee/opcode_results/CLEARITEMS.csv new file mode 100644 index 0000000000..2655fedf9c --- /dev/null +++ b/opcodefee/opcode_results/CLEARITEMS.csv @@ -0,0 +1,33 @@ +opcode,elemtype,refcount,numitems,numiters,ns +CLEARITEMS,Array,256,1,100000,1767 +CLEARITEMS,Array,512,1,100000,3195 +CLEARITEMS,Array,768,1,100000,4970 +CLEARITEMS,Array,1024,1,100000,6041 +CLEARITEMS,Array,1280,1,100000,7177 +CLEARITEMS,Array,1536,1,100000,8649 +CLEARITEMS,Array,1792,1,100000,10026 +CLEARITEMS,Array,2048,1,100000,11192 +CLEARITEMS,Array,256,255,100000,2219 +CLEARITEMS,Array,512,511,100000,4123 +CLEARITEMS,Array,768,767,100000,5880 +CLEARITEMS,Array,1024,1023,100000,7773 +CLEARITEMS,Array,1280,1279,100000,9714 +CLEARITEMS,Array,1536,1535,100000,11645 +CLEARITEMS,Array,1792,1791,100000,13399 +CLEARITEMS,Array,2048,2047,100000,15286 +CLEARITEMS,Map,256,2,100000,1824 +CLEARITEMS,Map,512,2,100000,3195 +CLEARITEMS,Map,768,2,100000,4970 +CLEARITEMS,Map,1024,2,100000,6041 +CLEARITEMS,Map,1280,2,100000,7177 +CLEARITEMS,Map,1536,2,100000,8649 +CLEARITEMS,Map,1792,2,100000,10026 +CLEARITEMS,Map,2048,2,100000,11192 +CLEARITEMS,Map,255,254,100000,2219 +CLEARITEMS,Map,511,510,100000,4123 +CLEARITEMS,Map,767,766,100000,5880 +CLEARITEMS,Map,1023,1022,100000,7773 +CLEARITEMS,Map,1279,1278,100000,9714 +CLEARITEMS,Map,1535,1534,100000,11645 +CLEARITEMS,Map,1791,1790,100000,13399 +CLEARITEMS,Map,2047,2046,100000,15286 diff --git a/opcodefee/opcode_results/CONVERT.csv b/opcodefee/opcode_results/CONVERT.csv new file mode 100644 index 0000000000..5b6be75724 --- /dev/null +++ b/opcodefee/opcode_results/CONVERT.csv @@ -0,0 +1,17 @@ +opcode,fromtype,totype,itemsize,numiters,ns +CONVERT,Array,Struct,255,100000,4026 +CONVERT,Array,Struct,511,100000,6806 +CONVERT,Array,Struct,767,100000,10341 +CONVERT,Array,Struct,1023,100000,12733 +CONVERT,Array,Struct,1279,100000,16115 +CONVERT,Array,Struct,1535,100000,18535 +CONVERT,Array,Struct,1791,100000,22758 +CONVERT,Array,Struct,2047,100000,24321 +CONVERT,ByteString,Buffer,16383,100000,3418 +CONVERT,ByteString,Buffer,32766,100000,5644 +CONVERT,ByteString,Buffer,49149,100000,7942 +CONVERT,ByteString,Buffer,65532,100000,10260 +CONVERT,ByteString,Buffer,81915,100000,12914 +CONVERT,ByteString,Buffer,98298,100000,14802 +CONVERT,ByteString,Buffer,114681,100000,16741 +CONVERT,ByteString,Buffer,131064,100000,18956 diff --git a/opcodefee/opcode_results/DROP.csv b/opcodefee/opcode_results/DROP.csv new file mode 100644 index 0000000000..aeff191a4a --- /dev/null +++ b/opcodefee/opcode_results/DROP.csv @@ -0,0 +1,9 @@ +opcode,refcount,numiters,ns +DROP,256,100000,1847 +DROP,512,100000,3264 +DROP,768,100000,5581 +DROP,1024,100000,6826 +DROP,1280,100000,7255 +DROP,1536,100000,8745 +DROP,1792,100000,10527 +DROP,2048,100000,11511 diff --git a/opcodefee/opcode_results/DUP.csv b/opcodefee/opcode_results/DUP.csv new file mode 100644 index 0000000000..c5904eb65c --- /dev/null +++ b/opcodefee/opcode_results/DUP.csv @@ -0,0 +1,9 @@ +opcode,numbytes,numiters,ns +DUP,ByteString,16383,100000,3361 +DUP,ByteString,32766,100000,4669 +DUP,ByteString,49149,100000,7740 +DUP,ByteString,65532,100000,9233 +DUP,ByteString,81915,100000,10941 +DUP,ByteString,98298,100000,12287 +DUP,ByteString,114681,100000,13700 +DUP,ByteString,131064,100000,14730 diff --git a/opcodefee/opcode_results/HASKEY.csv b/opcodefee/opcode_results/HASKEY.csv new file mode 100644 index 0000000000..a75238216f --- /dev/null +++ b/opcodefee/opcode_results/HASKEY.csv @@ -0,0 +1,17 @@ +opcode,elemtype,elemsize,keytype,numiters,ns +HASKEY,Map,127,Integer,100000,3164 +HASKEY,Map,255,Integer,100000,5777 +HASKEY,Map,383,Integer,100000,17609 +HASKEY,Map,511,Integer,100000,27461 +HASKEY,Map,639,Integer,100000,33927 +HASKEY,Map,767,Integer,100000,40214 +HASKEY,Map,895,Integer,100000,46216 +HASKEY,Map,1023,Integer,100000,52526 +HASKEY,Map,127,ByteString,100000,7118 +HASKEY,Map,255,ByteString,100000,10816 +HASKEY,Map,383,ByteString,100000,15301 +HASKEY,Map,511,ByteString,100000,28623 +HASKEY,Map,639,ByteString,100000,35535 +HASKEY,Map,767,ByteString,100000,41648 +HASKEY,Map,895,ByteString,100000,48173 +HASKEY,Map,1023,ByteString,100000,54503 \ No newline at end of file diff --git a/opcodefee/opcode_results/INITSLOT.csv b/opcodefee/opcode_results/INITSLOT.csv new file mode 100644 index 0000000000..38e7c7dd57 --- /dev/null +++ b/opcodefee/opcode_results/INITSLOT.csv @@ -0,0 +1,17 @@ +opcode,localslots,argslots,numiters,ns +INITSLOT,31,0,100000,572.0 +INITSLOT,0,31,100000,1187 +INITSLOT,62,0,100000,609.9 +INITSLOT,0,62,100000,1804 +INITSLOT,93,0,100000,702.5 +INITSLOT,0,93,100000,2451 +INITSLOT,124,0,100000,769.2 +INITSLOT,0,124,100000,3051 +INITSLOT,155,0,100000,906.6 +INITSLOT,0,155,100000,3743 +INITSLOT,186,0,100000,883.9 +INITSLOT,0,186,100000,4255 +INITSLOT,217,0,100000,1122 +INITSLOT,0,217,100000,5089 +INITSLOT,248,0,100000,1119 +INITSLOT,0,248,100000,5623 diff --git a/opcodefee/opcode_results/INITSSLOT.csv b/opcodefee/opcode_results/INITSSLOT.csv new file mode 100644 index 0000000000..1a2a2ba60b --- /dev/null +++ b/opcodefee/opcode_results/INITSSLOT.csv @@ -0,0 +1,9 @@ +opcode,staticslots,numiters,ns +INITSSLOT,31,100000,574.3 +INITSSLOT,62,100000,622.9 +INITSSLOT,93,100000,726.3 +INITSSLOT,124,100000,762.3 +INITSSLOT,155,100000,922.7 +INITSSLOT,186,100000,899.8 +INITSSLOT,217,100000,1102 +INITSSLOT,248,100000,1168 \ No newline at end of file diff --git a/opcodefee/opcode_results/KEYS.csv b/opcodefee/opcode_results/KEYS.csv new file mode 100644 index 0000000000..1417030d5e --- /dev/null +++ b/opcodefee/opcode_results/KEYS.csv @@ -0,0 +1,17 @@ +opcode,elemsize,keytype,numiters,ns +KEYS,127,Integer,100000,10906 +KEYS,255,Integer,100000,20404 +KEYS,383,Integer,100000,58052 +KEYS,511,Integer,100000,88189 +KEYS,639,Integer,100000,104313 +KEYS,767,Integer,100000,117198 +KEYS,895,Integer,100000,129767 +KEYS,1023,Integer,100000,141325 +KEYS,127,ByteString,100000,18392 +KEYS,255,ByteString,100000,24500 +KEYS,383,ByteString,100000,82370 +KEYS,511,ByteString,100000,105308 +KEYS,639,ByteString,100000,127059 +KEYS,767,ByteString,100000,134414 +KEYS,895,ByteString,100000,151085 +KEYS,1023,ByteString,100000,169122 \ No newline at end of file diff --git a/opcodefee/opcode_results/MEMCPY.csv b/opcodefee/opcode_results/MEMCPY.csv new file mode 100644 index 0000000000..d543d4b4fe --- /dev/null +++ b/opcodefee/opcode_results/MEMCPY.csv @@ -0,0 +1,9 @@ +opcode,numbytes,numiters,ns +MEMCPY,16383,100000,716.3 +MEMCPY,32766,100000,1079 +MEMCPY,49149,100000,1451 +MEMCPY,65532,100000,1772 +MEMCPY,81915,100000,2248 +MEMCPY,98298,100000,2609 +MEMCPY,114681,100000,2989 +MEMCPY,131064,100000,3587 diff --git a/opcodefee/opcode_results/NEWARRAYT.csv b/opcodefee/opcode_results/NEWARRAYT.csv new file mode 100644 index 0000000000..d23e2d49ee --- /dev/null +++ b/opcodefee/opcode_results/NEWARRAYT.csv @@ -0,0 +1,33 @@ +opcode,elemsize,arraytype,numiters,ns +NEWARRAYT,255,Boolean,100000,3181 +NEWARRAYT,255,Integer,100000,13492 +NEWARRAYT,255,ByteString,100000,12920 +NEWARRAYT,255,Any,100000,3337 +NEWARRAYT,511,Boolean,100000,5304 +NEWARRAYT,511,Integer,100000,24036 +NEWARRAYT,511,ByteString,100000,23107 +NEWARRAYT,511,Any,100000,5666 +NEWARRAYT,767,Boolean,100000,7006 +NEWARRAYT,767,Integer,100000,33337 +NEWARRAYT,767,ByteString,100000,31493 +NEWARRAYT,767,Any,100000,7651 +NEWARRAYT,1023,Boolean,100000,9279 +NEWARRAYT,1023,Integer,100000,41870 +NEWARRAYT,1023,ByteString,100000,38732 +NEWARRAYT,1023,Any,100000,10124 +NEWARRAYT,1279,Boolean,100000,11490 +NEWARRAYT,1279,Integer,100000,49869 +NEWARRAYT,1279,ByteString,100000,47014 +NEWARRAYT,1279,Any,100000,12464 +NEWARRAYT,1535,Boolean,100000,13290 +NEWARRAYT,1535,Integer,100000,58649 +NEWARRAYT,1535,ByteString,100000,54190 +NEWARRAYT,1535,Any,100000,14291 +NEWARRAYT,1791,Boolean,100000,15455 +NEWARRAYT,1791,Integer,100000,66507 +NEWARRAYT,1791,ByteString,100000,62037 +NEWARRAYT,1791,Any,100000,16608 +NEWARRAYT,2047,Boolean,100000,17167 +NEWARRAYT,2047,Integer,100000,74072 +NEWARRAYT,2047,ByteString,100000,69210 +NEWARRAYT,2047,Any,100000,18449 diff --git a/opcodefee/opcode_results/NEWBUFFER.csv b/opcodefee/opcode_results/NEWBUFFER.csv new file mode 100644 index 0000000000..dde37891f9 --- /dev/null +++ b/opcodefee/opcode_results/NEWBUFFER.csv @@ -0,0 +1,9 @@ +opcode,numbytes,numiters,ns +NEWBUFFER,16383,100000,2810 +NEWBUFFER,32766,100000,4265 +NEWBUFFER,49149,100000,6529 +NEWBUFFER,65532,100000,8081 +NEWBUFFER,81915,100000,10088 +NEWBUFFER,98298,100000,12084 +NEWBUFFER,114681,100000,13253 +NEWBUFFER,131064,100000,14716 diff --git a/opcodefee/opcode_results/PACK.csv b/opcodefee/opcode_results/PACK.csv new file mode 100644 index 0000000000..f185d59c27 --- /dev/null +++ b/opcodefee/opcode_results/PACK.csv @@ -0,0 +1,17 @@ +opcode,refcount,elemsize,numiters,ns +PACK,255,1,100000,3881 +PACK,511,1,100000,6598 +PACK,767,1,100000,9300 +PACK,1023,1,100000,12276 +PACK,1279,1,100000,15067 +PACK,1535,1,100000,18221 +PACK,1791,1,100000,20967 +PACK,2047,1,100000,24276 +PACK,255,255,100000,5774 +PACK,511,511,100000,10816 +PACK,767,767,100000,15244 +PACK,1023,1023,100000,19880 +PACK,1279,1279,100000,22896 +PACK,1535,1535,100000,28208 +PACK,1791,1791,100000,32618 +PACK,2047,2047,100000,36221 diff --git a/opcodefee/opcode_results/PACKMAP.csv b/opcodefee/opcode_results/PACKMAP.csv new file mode 100644 index 0000000000..9cc42535b3 --- /dev/null +++ b/opcodefee/opcode_results/PACKMAP.csv @@ -0,0 +1,25 @@ +opcode,keytype,refcount,elemsize,numiters,ns +PACKMAP,Any,255,1,100000,4043 +PACKMAP,Any,511,1,100000,7034 +PACKMAP,Any,767,1,100000,9864 +PACKMAP,Any,1023,1,100000,12953 +PACKMAP,Any,1279,1,100000,15913 +PACKMAP,Any,1535,1,100000,18873 +PACKMAP,Any,1791,1,100000,21941 +PACKMAP,Any,2047,1,100000,25214 +PACKMAP,Integer,254,127,100000,86392 +PACKMAP,Integer,510,255,100000,302688 +PACKMAP,Integer,766,383,100000,658957 +PACKMAP,Integer,1022,511,100000,2661356 +PACKMAP,Integer,1278,639,100000,3895498 +PACKMAP,Integer,1534,767,100000,5290121 +PACKMAP,Integer,1790,895,100000,7083858 +PACKMAP,Integer,2046,1023,100000,9207018 +PACKMAP,ByteString,254,127,100000,229827 +PACKMAP,ByteString,510,255,100000,679607 +PACKMAP,ByteString,766,383,100000,706117 +PACKMAP,ByteString,1022,511,100000,2799167 +PACKMAP,ByteString,1278,639,100000,4252418 +PACKMAP,ByteString,1534,767,100000,5727771 +PACKMAP,ByteString,1790,895,100000,7702513 +PACKMAP,ByteString,2046,1023,100000,9950942 diff --git a/opcodefee/opcode_results/PICKITEM.csv b/opcodefee/opcode_results/PICKITEM.csv new file mode 100644 index 0000000000..c47066ac5e --- /dev/null +++ b/opcodefee/opcode_results/PICKITEM.csv @@ -0,0 +1,41 @@ +opcode,elemtype,refcount,elemsize,valuetype,valuesize,numiters,ns +PICKITEM,Array,255,1,Array,1,100000,3775 +PICKITEM,Array,511,1,Array,1,100000,6492 +PICKITEM,Array,767,1,Array,1,100000,9323 +PICKITEM,Array,1023,1,Array,1,100000,12076 +PICKITEM,Array,1279,1,Array,1,100000,15000 +PICKITEM,Array,1535,1,Array,1,100000,17698 +PICKITEM,Array,1791,1,Array,1,100000,20828 +PICKITEM,Array,2047,1,Array,1,100000,23828 +PICKITEM,Array,1,1,ByteString,16382,100000,5699 +PICKITEM,Array,1,1,ByteString,32765,100000,9602 +PICKITEM,Array,1,1,ByteString,49148,100000,13254 +PICKITEM,Array,1,1,ByteString,65531,100000,19316 +PICKITEM,Array,1,1,ByteString,81914,100000,22225 +PICKITEM,Array,1,1,ByteString,98297,100000,25715 +PICKITEM,Array,1,1,ByteString,114680,100000,27432 +PICKITEM,Array,1,1,ByteString,131063,100000,32275 +PICKITEM,Map,255,1,Array,1,100000,3851 +PICKITEM,Map,511,1,Array,1,100000,6761 +PICKITEM,Map,767,1,Array,1,100000,9674 +PICKITEM,Map,1023,1,Array,1,100000,12864 +PICKITEM,Map,1279,1,Array,1,100000,15910 +PICKITEM,Map,1535,1,Array,1,100000,18579 +PICKITEM,Map,1791,1,Array,1,100000,22105 +PICKITEM,Map,2047,1,Array,1,100000,25502 +PICKITEM,Map,1,255,Any,1,100000,3378 +PICKITEM,Map,1,511,Any,1,100000,6199 +PICKITEM,Map,1,767,Any,1,100000,8896 +PICKITEM,Map,1,1023,Any,1,100000,28331 +PICKITEM,Map,1,1279,Any,1,100000,35252 +PICKITEM,Map,1,1535,Any,1,100000,41626 +PICKITEM,Map,1,1791,Any,1,100000,48252 +PICKITEM,Map,1,2047,Any,1,100000,54696 +PICKITEM,Map,1,1,ByteString,16382,100000,8258 +PICKITEM,Map,1,1,ByteString,32765,100000,10234 +PICKITEM,Map,1,1,ByteString,49148,100000,13995 +PICKITEM,Map,1,1,ByteString,65531,100000,18875 +PICKITEM,Map,1,1,ByteString,81914,100000,22311 +PICKITEM,Map,1,1,ByteString,98297,100000,26483 +PICKITEM,Map,1,1,ByteString,114680,100000,27709 +PICKITEM,Map,1,1,ByteString,131063,100000,31879 \ No newline at end of file diff --git a/opcodefee/opcode_results/POPITEM.csv b/opcodefee/opcode_results/POPITEM.csv new file mode 100644 index 0000000000..f6b9d0c79d --- /dev/null +++ b/opcodefee/opcode_results/POPITEM.csv @@ -0,0 +1,9 @@ +opcode,refcount,numiters,ns +POPITEM,Array,256,100000,3461 +POPITEM,Array,512,100000,6175 +POPITEM,Array,768,100000,8994 +POPITEM,Array,1024,100000,11942 +POPITEM,Array,1280,100000,13846 +POPITEM,Array,1536,100000,16995 +POPITEM,Array,1792,100000,20303 +POPITEM,Array,2048,100000,22528 diff --git a/opcodefee/opcode_results/REMOVE.csv b/opcodefee/opcode_results/REMOVE.csv new file mode 100644 index 0000000000..961d511c4c --- /dev/null +++ b/opcodefee/opcode_results/REMOVE.csv @@ -0,0 +1,25 @@ +opcode,elemtype,refcount,elemsize,numiters,ns +REMOVE,Array,255,1,100000,1863 +REMOVE,Array,511,1,100000,3313 +REMOVE,Array,767,1,100000,5085 +REMOVE,Array,1023,1,100000,6226 +REMOVE,Array,1279,1,100000,7615 +REMOVE,Array,1535,1,100000,8760 +REMOVE,Array,1791,1,100000,10301 +REMOVE,Array,2047,1,100000,11526 +REMOVE,Map,255,1,100000,1911 +REMOVE,Map,511,1,100000,3414 +REMOVE,Map,767,1,100000,5050 +REMOVE,Map,1023,1,100000,6479 +REMOVE,Map,1279,1,100000,8083 +REMOVE,Map,1535,1,100000,9100 +REMOVE,Map,1791,1,100000,10775 +REMOVE,Map,2047,1,100000,11992 +REMOVE,Map,1,255,100000,3584 +REMOVE,Map,1,511,100000,6165 +REMOVE,Map,1,767,100000,9190 +REMOVE,Map,1,1023,100000,11433 +REMOVE,Map,1,1279,100000,14253 +REMOVE,Map,1,1535,100000,16988 +REMOVE,Map,1,1791,100000,19737 +REMOVE,Map,1,2047,100000,22045 \ No newline at end of file diff --git a/opcodefee/opcode_results/RET.csv b/opcodefee/opcode_results/RET.csv new file mode 100644 index 0000000000..d4cafa7307 --- /dev/null +++ b/opcodefee/opcode_results/RET.csv @@ -0,0 +1,17 @@ +opcode,refcount,stacksize,numiters,ns +CLEAR,256,1,100000,3203 +CLEAR,512,1,100000,5964 +CLEAR,768,1,100000,8605 +CLEAR,1024,1,100000,11299 +CLEAR,1280,1,100000,13722 +CLEAR,1536,1,100000,16583 +CLEAR,1792,1,100000,20552 +CLEAR,2048,1,100000,22434 +CLEAR,256,256,100000,16423 +CLEAR,512,512,100000,39550 +CLEAR,768,768,100000,70888 +CLEAR,1024,1024,100000,116131 +CLEAR,1280,1280,100000,169688 +CLEAR,1536,1536,100000,235612 +CLEAR,1792,1792,100000,309821 +CLEAR,2048,2048,100000,398399 diff --git a/opcodefee/opcode_results/REVERSEITEMS.csv b/opcodefee/opcode_results/REVERSEITEMS.csv new file mode 100644 index 0000000000..e428142e2d --- /dev/null +++ b/opcodefee/opcode_results/REVERSEITEMS.csv @@ -0,0 +1,17 @@ +opcode,elemtype,elemsize,numiters,ns +REVERSEITEMS,Array,256,100000,2379 +REVERSEITEMS,Buffer,16383,100000,107865 +REVERSEITEMS,Array,512,100000,4224 +REVERSEITEMS,Buffer,32766,100000,203691 +REVERSEITEMS,Array,768,100000,6121 +REVERSEITEMS,Buffer,49149,100000,296999 +REVERSEITEMS,Array,1024,100000,8149 +REVERSEITEMS,Buffer,65532,100000,417948 +REVERSEITEMS,Array,1280,100000,9529 +REVERSEITEMS,Buffer,81915,100000,460539 +REVERSEITEMS,Array,1536,100000,11994 +REVERSEITEMS,Buffer,98298,100000,551802 +REVERSEITEMS,Array,1792,100000,14047 +REVERSEITEMS,Buffer,114681,100000,629441 +REVERSEITEMS,Array,2048,100000,16929 +REVERSEITEMS,Buffer,131064,100000,771208 diff --git a/opcodefee/opcode_results/REVERSEN.csv b/opcodefee/opcode_results/REVERSEN.csv new file mode 100644 index 0000000000..73f506dbde --- /dev/null +++ b/opcodefee/opcode_results/REVERSEN.csv @@ -0,0 +1,9 @@ +opcode,n,numiters,ns +REVERSEN,255,100000,672.1 +REVERSEN,511,100000,1180 +REVERSEN,767,100000,1683 +REVERSEN,1023,100000,2408 +REVERSEN,1279,100000,2650 +REVERSEN,1535,100000,3725 +REVERSEN,1791,100000,4238 +REVERSEN,2047,100000,4568 diff --git a/opcodefee/opcode_results/ROLL.csv b/opcodefee/opcode_results/ROLL.csv new file mode 100644 index 0000000000..6a40daec4d --- /dev/null +++ b/opcodefee/opcode_results/ROLL.csv @@ -0,0 +1,9 @@ +opcode,n,numiters,ns +ROLL,254,100000,564.4 +ROLL,510,100000,859.5 +ROLL,766,100000,1333 +ROLL,1022,100000,1988 +ROLL,1278,100000,2071 +ROLL,1534,100000,3249 +ROLL,1790,100000,3724 +ROLL,2046,100000,4042 diff --git a/opcodefee/opcode_results/SETITEM.csv b/opcodefee/opcode_results/SETITEM.csv new file mode 100644 index 0000000000..75bc23401d --- /dev/null +++ b/opcodefee/opcode_results/SETITEM.csv @@ -0,0 +1,41 @@ +opcode,elemtype,removedrefcount,addedrefcount,elemsize,numiters,ns +SETITEM,Array,255,1,1,100000,2097 +SETITEM,Array,1,255,1,100000,3541 +SETITEM,Array,511,1,1,100000,3491 +SETITEM,Array,1,511,1,100000,6146 +SETITEM,Array,767,1,1,100000,5095 +SETITEM,Array,1,767,1,100000,9105 +SETITEM,Array,1023,1,1,100000,6613 +SETITEM,Array,1,1023,1,100000,11770 +SETITEM,Array,1279,1,1,100000,7802 +SETITEM,Array,1,1279,1,100000,13903 +SETITEM,Array,1535,1,1,100000,8901 +SETITEM,Array,1,1535,1,100000,17138 +SETITEM,Array,1791,1,1,100000,10517 +SETITEM,Array,1,1791,1,100000,20993 +SETITEM,Array,2047,1,1,100000,11643 +SETITEM,Array,1,2047,1,100000,22663 +SETITEM,Map,255,1,1,100000,1976 +SETITEM,Map,1,255,1,100000,3529 +SETITEM,Map,511,1,1,100000,3433 +SETITEM,Map,1,511,1,100000,6397 +SETITEM,Map,767,1,1,100000,5065 +SETITEM,Map,1,767,1,100000,9606 +SETITEM,Map,1023,1,1,100000,6637 +SETITEM,Map,1,1023,1,100000,12347 +SETITEM,Map,1279,1,1,100000,7962 +SETITEM,Map,1,1279,1,100000,14947 +SETITEM,Map,1535,1,1,100000,9309 +SETITEM,Map,1,1535,1,100000,17856 +SETITEM,Map,1791,1,1,100000,10916 +SETITEM,Map,1,1791,1,100000,21806 +SETITEM,Map,2047,1,1,100000,12167 +SETITEM,Map,1,2047,1,100000,23317 +SETITEM,Map,1,1,127,100000,5484 +SETITEM,Map,1,1,255,100000,10577 +SETITEM,Map,1,1,383,100000,14495 +SETITEM,Map,1,1,511,100000,18602 +SETITEM,Map,1,1,639,100000,22241 +SETITEM,Map,1,1,767,100000,26234 +SETITEM,Map,1,1,895,100000,30137 +SETITEM,Map,1,1,1023,100000,33795 diff --git a/opcodefee/opcode_results/ST.csv b/opcodefee/opcode_results/ST.csv new file mode 100644 index 0000000000..c5c4200d85 --- /dev/null +++ b/opcodefee/opcode_results/ST.csv @@ -0,0 +1,17 @@ +opcode,removedrefcount,addedrefcount,numiters,ns +ST,256,1,100000,1744 +ST,1,256,100000,3326 +ST,512,1,100000,3175 +ST,1,512,100000,6254 +ST,768,1,100000,4806 +ST,1,768,100000,8885 +ST,1024,1,100000,6329 +ST,1,1024,100000,12024 +ST,1280,1,100000,7549 +ST,1,1280,100000,14635 +ST,1536,1,100000,8859 +ST,1,1536,100000,18158 +ST,1792,1,100000,10836 +ST,1,1792,100000,20967 +ST,2048,1,100000,12211 +ST,1,2048,100000,24336 diff --git a/opcodefee/opcode_results/SUBSTR.csv b/opcodefee/opcode_results/SUBSTR.csv new file mode 100644 index 0000000000..e317c79ed4 --- /dev/null +++ b/opcodefee/opcode_results/SUBSTR.csv @@ -0,0 +1,9 @@ +opcode,numbytes,numiters,ns +CAT,16383,100000,3182 +CAT,32766,100000,5020 +CAT,49149,100000,7483 +CAT,65532,100000,10177 +CAT,81915,100000,13300 +CAT,98298,100000,14998 +CAT,114681,100000,19029 +CAT,131064,100000,21095 diff --git a/opcodefee/opcode_results/UNPACK.csv b/opcodefee/opcode_results/UNPACK.csv new file mode 100644 index 0000000000..5cd1a3e89e --- /dev/null +++ b/opcodefee/opcode_results/UNPACK.csv @@ -0,0 +1,33 @@ +opcode,elemtype,refcount,elemsize,numiters,ns +UNPACK,Array,255,1,100000,3909 +UNPACK,Array,511,1,100000,6882 +UNPACK,Array,767,1,100000,9697 +UNPACK,Array,1023,1,100000,12681 +UNPACK,Array,1279,1,100000,15699 +UNPACK,Array,1535,1,100000,18255 +UNPACK,Array,1791,1,100000,21051 +UNPACK,Array,2047,1,100000,24256 +UNPACK,Array,255,255,100000,8309 +UNPACK,Array,511,511,100000,15881 +UNPACK,Array,767,767,100000,26724 +UNPACK,Array,1023,1023,100000,37432 +UNPACK,Array,1279,1279,100000,39184 +UNPACK,Array,1535,1535,100000,57408 +UNPACK,Array,1791,1791,100000,60163 +UNPACK,Array,2047,2047,100000,62717 +UNPACK,Map,255,1,100000,4216 +UNPACK,Map,511,1,100000,7213 +UNPACK,Map,767,1,100000,10198 +UNPACK,Map,1023,1,100000,13112 +UNPACK,Map,1279,1,100000,16450 +UNPACK,Map,1535,1,100000,19232 +UNPACK,Map,1791,1,100000,22756 +UNPACK,Map,2047,1,100000,26446 +UNPACK,Map,254,127,100000,6493 +UNPACK,Map,510,255,100000,10667 +UNPACK,Map,766,383,100000,16173 +UNPACK,Map,1022,511,100000,42724 +UNPACK,Map,1278,639,100000,63370 +UNPACK,Map,1534,767,100000,62377 +UNPACK,Map,1790,895,100000,86145 +UNPACK,Map,2046,1023,100000,91387 diff --git a/opcodefee/opcode_results/VALUES.csv b/opcodefee/opcode_results/VALUES.csv new file mode 100644 index 0000000000..54b2e806dc --- /dev/null +++ b/opcodefee/opcode_results/VALUES.csv @@ -0,0 +1,65 @@ +opcode,elemtype,valuetype,refcount,elemsize,numiters,ns +VALUES,Array,Any,255,1,100000,3974 +VALUES,Array,Any,511,1,100000,6837 +VALUES,Array,Any,767,1,100000,9587 +VALUES,Array,Any,1023,1,100000,12408 +VALUES,Array,Any,1279,1,100000,15182 +VALUES,Array,Any,1535,1,100000,17750 +VALUES,Array,Any,1791,1,100000,20931 +VALUES,Array,Any,2047,1,100000,23952 +VALUES,Array,Struct,255,1,100000,29833 +VALUES,Array,Struct,511,1,100000,56898 +VALUES,Array,Struct,767,1,100000,77943 +VALUES,Array,Struct,1023,1,100000,104783 +VALUES,Array,Struct,1279,1,100000,124048 +VALUES,Array,Struct,1535,1,100000,144608 +VALUES,Array,Struct,1791,1,100000,170735 +VALUES,Array,Struct,2047,1,100000,199568 +VALUES,Array,Any,255,255,100000,6250 +VALUES,Array,Any,511,511,100000,12812 +VALUES,Array,Any,767,767,100000,16963 +VALUES,Array,Any,1023,1023,100000,21306 +VALUES,Array,Any,1279,1279,100000,24995 +VALUES,Array,Any,1535,1535,100000,29732 +VALUES,Array,Any,1791,1791,100000,33717 +VALUES,Array,Any,2047,2047,100000,38288 +VALUES,Array,Struct,255,255,100000,6250 +VALUES,Array,Struct,511,511,100000,12812 +VALUES,Array,Struct,767,767,100000,16963 +VALUES,Array,Struct,1023,1023,100000,21306 +VALUES,Array,Struct,1279,1279,100000,24995 +VALUES,Array,Struct,1535,1535,100000,29732 +VALUES,Array,Struct,1791,1791,100000,33717 +VALUES,Array,Struct,2047,2047,100000,38288 +VALUES,Map,Any,255,1,100000,4188 +VALUES,Map,Any,511,1,100000,7144 +VALUES,Map,Any,767,1,100000,10202 +VALUES,Map,Any,1023,1,100000,13019 +VALUES,Map,Any,1279,1,100000,16312 +VALUES,Map,Any,1535,1,100000,18851 +VALUES,Map,Any,1791,1,100000,22182 +VALUES,Map,Any,2047,1,100000,25636 +VALUES,Map,Struct,255,1,100000,30503 +VALUES,Map,Struct,511,1,100000,56278 +VALUES,Map,Struct,767,1,100000,77103 +VALUES,Map,Struct,1023,1,100000,103367 +VALUES,Map,Struct,1279,1,100000,124215 +VALUES,Map,Struct,1535,1,100000,145542 +VALUES,Map,Struct,1791,1,100000,169789 +VALUES,Map,Struct,2047,1,100000,198285 +VALUES,Map,Any,255,255,100000,3688 +VALUES,Map,Any,511,511,100000,6452 +VALUES,Map,Any,767,767,100000,9167 +VALUES,Map,Any,1023,1023,100000,27388 +VALUES,Map,Any,1279,1279,100000,34979 +VALUES,Map,Any,1535,1535,100000,41283 +VALUES,Map,Any,1791,1791,100000,47185 +VALUES,Map,Any,2047,2047,100000,53963 +VALUES,Map,Struct,255,255,100000,3688 +VALUES,Map,Struct,511,511,100000,6452 +VALUES,Map,Struct,767,767,100000,9167 +VALUES,Map,Struct,1023,1023,100000,27388 +VALUES,Map,Struct,1279,1279,100000,34979 +VALUES,Map,Struct,1535,1535,100000,41283 +VALUES,Map,Struct,1791,1791,100000,47185 +VALUES,Map,Struct,2047,2047,100000,53963 diff --git a/opcodefee/opcode_results/XDROP.csv b/opcodefee/opcode_results/XDROP.csv new file mode 100644 index 0000000000..4ca3108bb8 --- /dev/null +++ b/opcodefee/opcode_results/XDROP.csv @@ -0,0 +1,17 @@ +opcode,refcount,elemsize,numiters,ns +XDROP,256,1,100000,2287 +XDROP,512,1,100000,3610 +XDROP,768,1,100000,5013 +XDROP,1024,1,100000,6294 +XDROP,1280,1,100000,7630 +XDROP,1536,1,100000,9332 +XDROP,1792,1,100000,10356 +XDROP,2048,1,100000,11755 +XDROP,1,254,100000,869.5 +XDROP,1,510,100000,1281 +XDROP,1,766,100000,1473 +XDROP,1,1022,100000,1966 +XDROP,1,1278,100000,2023 +XDROP,1,1534,100000,3101 +XDROP,1,1790,100000,3433 +XDROP,1,2046,100000,3805 diff --git a/opcodefee/pack.ipynb b/opcodefee/pack.ipynb new file mode 100644 index 0000000000..bb6b88d3b7 --- /dev/null +++ b/opcodefee/pack.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/PACK.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/packmap.ipynb b/opcodefee/packmap.ipynb new file mode 100644 index 0000000000..252a9b2a3c --- /dev/null +++ b/opcodefee/packmap.ipynb @@ -0,0 +1,141 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/PACKMAP.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"elemsizesquare\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "df[\"elemsizesquare\"] = df[\"elemsize\"] ** 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"keytype\"] == \"Integer\") | (df[\"keytype\"] == \"Any\")])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"keytype\"] == \"ByteString\") | (df[\"keytype\"] == \"Any\")])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/pickitem.ipynb b/opcodefee/pickitem.ipynb new file mode 100644 index 0000000000..30b9fdce2c --- /dev/null +++ b/opcodefee/pickitem.ipynb @@ -0,0 +1,154 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/PICKITEM.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame, lstVariableNames):\n", + " X = df_type[lstVariableNames]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Array\") & (df[\"valuetype\"] == \"Array\")], [\"refcount\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Array\") & (df[\"valuetype\"] == \"ByteString\")], [\"valuesize\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Map\") & ((df[\"valuetype\"] == \"Array\") | (df[\"valuetype\"] == \"Any\"))], [\"elemsize\", \"refcount\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Map\") & ((df[\"valuetype\"] == \"ByteString\") | (df[\"valuetype\"] == \"Any\"))], [\"elemsize\", \"valuesize\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/popitem.ipynb b/opcodefee/popitem.ipynb new file mode 100644 index 0000000000..4fa980c516 --- /dev/null +++ b/opcodefee/popitem.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/POPITEM.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/remove.ipynb b/opcodefee/remove.ipynb new file mode 100644 index 0000000000..5c0ee52d77 --- /dev/null +++ b/opcodefee/remove.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/REMOVE.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame, lstVariableNames):\n", + " X = df_type[lstVariableNames]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Array\"], [\"refcount\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Map\"], [\"refcount\", \"elemsize\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/ret.ipynb b/opcodefee/ret.ipynb new file mode 100644 index 0000000000..4109029db3 --- /dev/null +++ b/opcodefee/ret.ipynb @@ -0,0 +1,130 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/RET.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"stacksizesquare\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "df[\"stacksizesquare\"] = df[\"stacksize\"] ** 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/reverseitems.ipynb b/opcodefee/reverseitems.ipynb new file mode 100644 index 0000000000..dfb4caeff1 --- /dev/null +++ b/opcodefee/reverseitems.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/REVERSEITEMS.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Array\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Buffer\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/reversen.ipynb b/opcodefee/reversen.ipynb new file mode 100644 index 0000000000..3879dc074b --- /dev/null +++ b/opcodefee/reversen.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/REVERSEN.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"n\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/roll.ipynb b/opcodefee/roll.ipynb new file mode 100644 index 0000000000..3fea686ceb --- /dev/null +++ b/opcodefee/roll.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/ROLL.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"n\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/setitem.ipynb b/opcodefee/setitem.ipynb new file mode 100644 index 0000000000..c3cad96fad --- /dev/null +++ b/opcodefee/setitem.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/SETITEM.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame, lstVariableNames):\n", + " X = df_type[lstVariableNames]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Array\"], [\"removedrefcount\", \"addedrefcount\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Map\"], [\"removedrefcount\", \"addedrefcount\", \"elemsize\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/st.ipynb b/opcodefee/st.ipynb new file mode 100644 index 0000000000..6c146c66e2 --- /dev/null +++ b/opcodefee/st.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/ST.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"removedrefcount\", \"addedrefcount\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/substr.ipynb b/opcodefee/substr.ipynb new file mode 100644 index 0000000000..0e092851fe --- /dev/null +++ b/opcodefee/substr.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/SUBSTR.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"numbytes\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/unpack.ipynb b/opcodefee/unpack.ipynb new file mode 100644 index 0000000000..c5f04e61f3 --- /dev/null +++ b/opcodefee/unpack.ipynb @@ -0,0 +1,132 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/UNPACK.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Array\"])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df[df[\"elemtype\"] == \"Map\"])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/values.ipynb b/opcodefee/values.ipynb new file mode 100644 index 0000000000..f46e245d1d --- /dev/null +++ b/opcodefee/values.ipynb @@ -0,0 +1,154 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/VALUES.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Array\") & (df[\"valuetype\"] == \"Any\")])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Array\") & (df[\"valuetype\"] == \"Struct\")])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Map\") & (df[\"valuetype\"] == \"Any\")])\n", + "print(beta)\n", + "print(r2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df.loc[(df[\"elemtype\"] == \"Map\") & (df[\"valuetype\"] == \"Struct\")])\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/opcodefee/xdrop.ipynb b/opcodefee/xdrop.ipynb new file mode 100644 index 0000000000..c58b265795 --- /dev/null +++ b/opcodefee/xdrop.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import r2_score" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "df = pd.read_csv('opcode_results/XDROP.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_target_vs_each_feature(X: pd.DataFrame, y: pd.Series):\n", + " y_vals = y.values.reshape(-1)\n", + " for col in X.columns:\n", + " x_vals = X[col].values\n", + " plt.figure(figsize=(8, 5))\n", + " plt.scatter(x_vals, y_vals)\n", + " plt.xlabel(col)\n", + " plt.ylabel(\"ns\")\n", + " plt.title(f\"ns vs {col}\")\n", + " plt.grid(True)\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def analytic_linear_regression(X: pd.DataFrame, y: pd.Series) -> np.ndarray:\n", + " X_mat = X.values\n", + " y_vec = y.values\n", + "\n", + " n = X_mat.shape[0]\n", + " X_design = np.hstack([X_mat, np.ones((n, 1))])\n", + "\n", + " beta, _, _, _ = np.linalg.lstsq(X_design, y_vec, rcond=None)\n", + "\n", + " return beta" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def myfunc(df_type: pd.DataFrame):\n", + " X = df_type[[\"refcount\", \"elemsize\"]]\n", + " y = df_type[\"ns\"]\n", + "\n", + " plot_target_vs_each_feature(X, y)\n", + " \n", + " X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.3, random_state=42\n", + " )\n", + " beta = analytic_linear_regression(X_train, y_train)\n", + " \n", + " X_test_mat = X_test.values\n", + " X_test_design = np.hstack([X_test_mat, np.ones((X_test_mat.shape[0], 1))])\n", + " y_pred = X_test_design @ beta\n", + " r2 = r2_score(y_test, y_pred)\n", + " \n", + " return beta, r2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "beta, r2 = myfunc(df)\n", + "print(beta)\n", + "print(r2)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "opcode", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pkg/core/fee/opcode.go b/pkg/core/fee/opcode.go index 5424999bc3..06a21e5b1f 100644 --- a/pkg/core/fee/opcode.go +++ b/pkg/core/fee/opcode.go @@ -2,6 +2,61 @@ package fee import ( "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "gonum.org/v1/gonum/floats" +) + +const ( + nopNS = 111.173603 +) + +var ( + appendAnyW = []float64{11.73069586, 350.41674237} + appendStructW = []float64{87.30446039, 17982.61841388} + catW = []float64{1.32937716e-01, 7.02639535e+02} + clearW = []float64{5.67140448, -0.73312282, 298.39230503} + clearItemsW = []float64{5.28724817, 1.88144976, 516.52124099} + convertArrayW = []float64{11.60835938, 1192.48835938} + convertByteArrayW = []float64{1.35404383e-01, 1.35296000e+03} + dropW = []float64{4.75086301, 1772.40697674} + dupW = []float64{8.63749860e-02, 3.62736047e+03} + hasKeyIntegerW = []float64{52.79587573, -891.9134266} + hasKeyByteArrayW = []float64{58.0377907, -3630.68313953} + initSlotW = []float64{2.64587955, 20.75369237, 470.12611159} + keysByteArrayW = []float64{130, 37481} + keysIntegerW = []float64{123, 19510} + memcpyW = []float64{2.57151131e-02, 1.34430233e+02} + newArrayBooleanW = []float64{7.93995276, 1111.14925509} + newArrayIntegerW = []float64{31.89135174, 9076.28670058} + newArrayByteArrayW = []float64{29.65833939, 8727.1699673} + newArrayAnyW = []float64{8.40720385, 1445.4885992} + newBuffer = []float64{1.00956181e-01, 1.60198837e+03} + packW = []float64{10.77058596, 6.29235395, 1629.89894874} + packMapIntegerW = []float64{1.28644848e+02, 8.83537843e+00, -1.74640868e+05} + packMapByteArrayW = []float64{3.90458381e+01, 9.57439349e+00, -3.69134485e+04} + pickItemAnyAnyW = []float64{11.35446948, 525.93586483} + pickItemAnyByteArrayW = []float64{2.13154163e-01, 4.04324804e+03} + pickItemMapAnyW = []float64{29.57506086, 16.10914509, -5696.71848299} + pickItemMapByteArrayW = []float64{2.58620558e+01, 2.56974509e-01, 4.87687014e+02} + popItemW = []float64{10.72283794, 699.34883721} + removeArrayW = []float64{5.10601381, 1097.15252544} + removeMapW = []float64{5.41334121, 10.31069302, 993.41112468} + retW = []float64{4.87054774e+00, 9.08958062e-02, 1.05882523e+04} + reverseItemsArrayW = []float64{8.30759448, -529.41860465} + reverseItemsBufferW = []float64{5.42999763e+00, 3.48448837e+04} + reverseW = []float64{2.31359012, -86.59338663} + rollW = []float64{2.19313227, -395.79978198} + setitemAnyW = []float64{5.4464, 10.61103203, 770.70123528} + setitemMapW = []float64{5.14137346, 10.61948722, 32.23029414, 1426.78225675} + stW = []float64{5.8727105, 11.69145319, 131.27384571} + substrW = []float64{1.69512072e-01, -7.79627907e+02} + unpackAnyW = []float64{10.76466731, 19.61487305, 1862.62836781} + unpackMapW = []float64{18.7980629, 61.54088073, -9239.49545835} + valuesAnyAnyW = []float64{10.15299821, 7.60633215, 2549.89349556} + valuesAnyStructW = []float64{94.83527304, -78.29029852, 4157.9709503} + valuesMapAnyW = []float64{15.9299167, 12.9647698, -5187.57312918} + valuesMapStructW = []float64{99.34192445, -71.5646272, -3707.90104081} + xDropW = []float64{5.55128018, 1.47575047, 489.35047339} ) // Opcode returns the deployment coefficients of the specified opcodes. @@ -211,3 +266,613 @@ var coefficients = [256]uint16{ opcode.ISTYPE: 1 << 1, opcode.CONVERT: 1 << 13, } + +func OpcodeStatic(base int64, op opcode.Opcode) int64 { + return base * staticCoefficients[op] +} + +var staticCoefficients = [256]int64{ + opcode.PUSHINT8: 1 << 2, + opcode.PUSHINT16: 1 << 2, + opcode.PUSHINT32: 1 << 2, + opcode.PUSHINT64: 1 << 2, + opcode.PUSHINT128: 1 << 2, + opcode.PUSHINT256: 1 << 2, + opcode.PUSHT: 1 << 0, + opcode.PUSHF: 1 << 0, + opcode.PUSHA: 1 << 2, + opcode.PUSHNULL: 1 << 0, + opcode.PUSHDATA1: 3, + opcode.PUSHDATA2: 3, + opcode.PUSHDATA4: 3, + opcode.PUSHM1: 3, + opcode.PUSH0: 3, + opcode.PUSH1: 3, + opcode.PUSH2: 3, + opcode.PUSH3: 3, + opcode.PUSH4: 3, + opcode.PUSH5: 3, + opcode.PUSH6: 3, + opcode.PUSH7: 3, + opcode.PUSH8: 3, + opcode.PUSH9: 3, + opcode.PUSH10: 3, + opcode.PUSH11: 3, + opcode.PUSH12: 3, + opcode.PUSH13: 3, + opcode.PUSH14: 3, + opcode.PUSH15: 3, + opcode.PUSH16: 3, + opcode.NOP: 1 << 0, + opcode.JMP: 1 << 0, + opcode.JMPL: 1 << 0, + opcode.JMPIF: 1 << 0, + opcode.JMPIFL: 1 << 0, + opcode.JMPIFNOT: 1 << 0, + opcode.JMPIFNOTL: 1 << 0, + opcode.JMPEQ: 1 << 1, + opcode.JMPEQL: 1 << 1, + opcode.JMPNE: 1 << 1, + opcode.JMPNEL: 1 << 1, + opcode.JMPGT: 1 << 1, + opcode.JMPGTL: 1 << 1, + opcode.JMPGE: 1 << 1, + opcode.JMPGEL: 1 << 1, + opcode.JMPLT: 1 << 1, + opcode.JMPLTL: 1 << 1, + opcode.JMPLE: 1 << 1, + opcode.JMPLEL: 1 << 1, + opcode.CALL: 3, + opcode.CALLL: 3, + opcode.CALLA: 3, + opcode.CALLT: 1 << 15, + opcode.ABORT: 0, + opcode.ASSERT: 1 << 0, + opcode.ABORTMSG: 0, + opcode.ASSERTMSG: 1 << 0, + opcode.THROW: 1 << 9, + opcode.TRY: 1 << 2, + opcode.TRYL: 1 << 2, + opcode.ENDTRY: 1 << 2, + opcode.ENDTRYL: 1 << 2, + opcode.ENDFINALLY: 1 << 2, + opcode.RET: 0, + opcode.SYSCALL: 0, + opcode.DEPTH: 1 << 0, + opcode.DROP: 1 << 0, + opcode.NIP: 1 << 0, + opcode.XDROP: 1 << 0, + opcode.CLEAR: 1 << 0, + opcode.DUP: 1 << 0, + opcode.OVER: 1 << 0, + opcode.PICK: 1 << 0, + opcode.TUCK: 1 << 0, + opcode.SWAP: 1 << 1, + opcode.ROT: 1 << 0, + opcode.ROLL: 1 << 0, + opcode.REVERSE3: 1 << 0, + opcode.REVERSE4: 1 << 0, + opcode.REVERSEN: 1 << 0, + opcode.INITSSLOT: 1 << 0, + opcode.INITSLOT: 1 << 0, + opcode.LDSFLD0: 1 << 0, + opcode.LDSFLD1: 1 << 0, + opcode.LDSFLD2: 1 << 0, + opcode.LDSFLD3: 1 << 0, + opcode.LDSFLD4: 1 << 0, + opcode.LDSFLD5: 1 << 0, + opcode.LDSFLD6: 1 << 0, + opcode.LDSFLD: 1 << 0, + opcode.STSFLD0: 1 << 0, + opcode.STSFLD1: 1 << 0, + opcode.STSFLD2: 1 << 0, + opcode.STSFLD3: 1 << 0, + opcode.STSFLD4: 1 << 0, + opcode.STSFLD5: 1 << 0, + opcode.STSFLD6: 1 << 0, + opcode.STSFLD: 1 << 0, + opcode.LDLOC0: 1 << 0, + opcode.LDLOC1: 1 << 0, + opcode.LDLOC2: 1 << 0, + opcode.LDLOC3: 1 << 0, + opcode.LDLOC4: 1 << 0, + opcode.LDLOC5: 1 << 0, + opcode.LDLOC6: 1 << 0, + opcode.LDLOC: 1 << 0, + opcode.STLOC0: 1 << 0, + opcode.STLOC1: 1 << 0, + opcode.STLOC2: 1 << 0, + opcode.STLOC3: 1 << 0, + opcode.STLOC4: 1 << 0, + opcode.STLOC5: 1 << 0, + opcode.STLOC6: 1 << 0, + opcode.STLOC: 1 << 0, + opcode.LDARG0: 1 << 0, + opcode.LDARG1: 1 << 0, + opcode.LDARG2: 1 << 0, + opcode.LDARG3: 1 << 0, + opcode.LDARG4: 1 << 0, + opcode.LDARG5: 1 << 0, + opcode.LDARG6: 1 << 0, + opcode.LDARG: 1 << 0, + opcode.STARG0: 1 << 0, + opcode.STARG1: 1 << 0, + opcode.STARG2: 1 << 0, + opcode.STARG3: 1 << 0, + opcode.STARG4: 1 << 0, + opcode.STARG5: 1 << 0, + opcode.STARG6: 1 << 0, + opcode.STARG: 1 << 0, + opcode.NEWBUFFER: 1 << 2, + opcode.MEMCPY: 1 << 0, + opcode.CAT: 1 << 0, + opcode.SUBSTR: 1 << 0, + opcode.LEFT: 1 << 0, + opcode.RIGHT: 1 << 0, + opcode.INVERT: 1 << 2, + opcode.AND: 1 << 3, + opcode.OR: 1 << 3, + opcode.XOR: 1 << 3, + opcode.EQUAL: 1 << 5, + opcode.NOTEQUAL: 1 << 5, + opcode.SIGN: 1 << 2, + opcode.ABS: 1 << 2, + opcode.NEGATE: 1 << 2, + opcode.INC: 1 << 2, + opcode.DEC: 3, + opcode.ADD: 1 << 3, + opcode.SUB: 1 << 3, + opcode.MUL: 1 << 3, + opcode.DIV: 1 << 3, + opcode.MOD: 1 << 3, + opcode.POW: 1 << 6, + opcode.SQRT: 1 << 6, + opcode.MODMUL: 1 << 5, + opcode.MODPOW: 1 << 11, + opcode.SHL: 1 << 3, + opcode.SHR: 1 << 3, + opcode.NOT: 1 << 2, + opcode.BOOLAND: 1 << 3, + opcode.BOOLOR: 1 << 3, + opcode.NZ: 1 << 2, + opcode.NUMEQUAL: 1 << 3, + opcode.NUMNOTEQUAL: 1 << 3, + opcode.LT: 1 << 3, + opcode.LE: 1 << 3, + opcode.GT: 1 << 3, + opcode.GE: 1 << 3, + opcode.MIN: 1 << 3, + opcode.MAX: 1 << 3, + opcode.WITHIN: 1 << 3, + opcode.PACKMAP: 1 << 0, + opcode.PACKSTRUCT: 1 << 0, + opcode.PACK: 1 << 0, + opcode.UNPACK: 1 << 0, + opcode.NEWARRAY0: 1 << 4, + opcode.NEWARRAY: 1 << 0, + opcode.NEWARRAYT: 1 << 0, + opcode.NEWSTRUCT0: 1 << 4, + opcode.NEWSTRUCT: 1 << 0, + opcode.NEWMAP: 1 << 3, + opcode.SIZE: 1 << 2, + opcode.HASKEY: 1 << 0, + opcode.KEYS: 1 << 0, + opcode.VALUES: 1 << 0, + opcode.PICKITEM: 1 << 0, + opcode.APPEND: 1 << 0, + opcode.SETITEM: 1 << 0, + opcode.REVERSEITEMS: 1 << 0, + opcode.REMOVE: 1 << 0, + opcode.CLEARITEMS: 1 << 0, + opcode.POPITEM: 1 << 0, + opcode.ISNULL: 1 << 1, + opcode.ISTYPE: 1 << 1, + opcode.CONVERT: 1 << 0, +} + +func OpcodeDynamic(base int64, op opcode.Opcode, args ...any) int64 { + return base * max(1, int64(dynamicPrices[op](args...)/nopNS)) +} + +var dynamicPrices = [256]func(args ...any) float64{ + opcode.APPEND: AppendGas, + opcode.CAT: CatGas, + opcode.CLEAR: ClearGas, + opcode.CLEARITEMS: ClearItemsGas, + opcode.CONVERT: ConvertGas, + opcode.DROP: DropGas, + opcode.DUP: DupGas, + opcode.HASKEY: HasKeyGas, + opcode.INITSLOT: InitSlotGas, + opcode.INITSSLOT: InitSlotGas, + opcode.KEYS: KeysGas, + opcode.LEFT: SubstrGas, + opcode.MEMCPY: MemcpyGas, + opcode.NEWARRAY: NewArrayGas, + opcode.NEWARRAYT: NewArrayGas, + opcode.NEWBUFFER: NewBufferGas, + opcode.NEWSTRUCT: NewArrayGas, + opcode.NIP: DropGas, + opcode.OVER: DupGas, + opcode.PACK: PackGas, + opcode.PACKMAP: PackMapGas, + opcode.PACKSTRUCT: PackGas, + opcode.PICKITEM: PickItemGas, + opcode.POPITEM: PopItemGas, + opcode.REMOVE: RemoveGas, + opcode.RET: RetGas, + opcode.REVERSEITEMS: ReverseItemsGas, + opcode.REVERSE3: ReverseGas, + opcode.REVERSE4: ReverseGas, + opcode.REVERSEN: ReverseGas, + opcode.RIGHT: SubstrGas, + opcode.ROLL: RollGas, + opcode.ROT: RollGas, + opcode.SETITEM: SetItemGas, + opcode.STSFLD0: STGas, + opcode.STSFLD1: STGas, + opcode.STSFLD2: STGas, + opcode.STSFLD3: STGas, + opcode.STSFLD4: STGas, + opcode.STSFLD5: STGas, + opcode.STSFLD6: STGas, + opcode.STSFLD: STGas, + opcode.STLOC0: STGas, + opcode.STLOC1: STGas, + opcode.STLOC2: STGas, + opcode.STLOC3: STGas, + opcode.STLOC4: STGas, + opcode.STLOC5: STGas, + opcode.STLOC6: STGas, + opcode.STLOC: STGas, + opcode.STARG0: STGas, + opcode.STARG1: STGas, + opcode.STARG2: STGas, + opcode.STARG3: STGas, + opcode.STARG4: STGas, + opcode.STARG5: STGas, + opcode.STARG6: STGas, + opcode.STARG: STGas, + opcode.SUBSTR: SubstrGas, + opcode.UNPACK: UnpackGas, + opcode.VALUES: ValuesGas, + opcode.XDROP: XDropGas, +} + +func AppendGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + r = args[1].(int) + ) + if t == stackitem.AnyT { + return floats.Dot(appendAnyW, []float64{float64(r), 1}) + } + return floats.Dot(appendStructW, []float64{float64(r), 1}) +} + +func CatGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + r := args[0].(int) + return floats.Dot(catW, []float64{float64(r), 1}) +} + +func ClearGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + r := args[0].(int) + s := args[1].(int) + return floats.Dot(clearW, []float64{float64(r), float64(s), 1}) +} + +func ClearItemsGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + r = args[0].(int) + l = args[1].(int) + ) + return floats.Dot(clearItemsW, []float64{float64(r), float64(l), 1}) +} + +func ConvertGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + l = args[1].(int) + ) + if t == stackitem.ArrayT { + return floats.Dot(convertArrayW, []float64{float64(l), 1}) + } + return floats.Dot(convertByteArrayW, []float64{float64(l), 1}) +} + +func DropGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + r := args[0].(int) + return floats.Dot(dropW, []float64{float64(r), 1}) +} + +func DupGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + l := args[0].(int) + return floats.Dot(dupW, []float64{float64(l), 1}) +} + +func HasKeyGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + l = args[1].(int) + ) + if t == stackitem.ByteArrayT { + return floats.Dot(hasKeyByteArrayW, []float64{float64(l), 1}) + } + return floats.Dot(hasKeyIntegerW, []float64{float64(l), 1}) +} + +func InitSlotGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + l := args[0].(byte) + a := args[1].(byte) + return floats.Dot(initSlotW, []float64{float64(l), float64(a), 1}) +} + +func KeysGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + l = args[1].(int) + ) + if t == stackitem.ByteArrayT { + return floats.Dot(keysByteArrayW, []float64{float64(l), 1}) + } + return floats.Dot(keysIntegerW, []float64{float64(l), 1}) +} + +func MemcpyGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + l := args[0].(int) + return floats.Dot(memcpyW, []float64{float64(l), 1}) +} + +func NewArrayGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + l = args[1].(int) + ) + switch t { + case stackitem.BooleanT: + return floats.Dot(newArrayBooleanW, []float64{float64(l), 1}) + case stackitem.IntegerT: + return floats.Dot(newArrayIntegerW, []float64{float64(l), 1}) + case stackitem.ByteArrayT: + return floats.Dot(newArrayByteArrayW, []float64{float64(l), 1}) + default: + return floats.Dot(newArrayAnyW, []float64{float64(l), 1}) + } +} + +func NewBufferGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + l := args[0].(int) + return floats.Dot(newBuffer, []float64{float64(l), 1}) +} + +func PackGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + r = args[0].(int) + l = args[1].(int) + ) + return floats.Dot(packW, []float64{float64(r), float64(l), 1}) +} + +func PackMapGas(args ...any) float64 { + if len(args) != 3 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + r = args[1].(int) + l = args[2].(int) + ) + if t == stackitem.ByteArrayT { + return floats.Dot(packMapByteArrayW, []float64{float64(r), float64(l), 1}) + } + return floats.Dot(packMapIntegerW, []float64{float64(r), float64(l), 1}) +} + +func PickItemGas(args ...any) float64 { + if len(args) != 4 { + panic("invalid arg len") + } + var ( + et = args[0].(stackitem.Type) + it = args[1].(stackitem.Type) + l = args[2].(int) + n = args[3].(int) + ) + if et == stackitem.MapT { + if it == stackitem.ByteArrayT { + return floats.Dot(pickItemMapByteArrayW, []float64{float64(l), float64(n), 1}) + } + return floats.Dot(pickItemMapAnyW, []float64{float64(l), float64(n), 1}) + } + if it == stackitem.ByteArrayT { + return floats.Dot(pickItemAnyByteArrayW, []float64{float64(n), 1}) + } + return floats.Dot(pickItemAnyAnyW, []float64{float64(n), 1}) +} + +func PopItemGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + r := args[0].(int) + return floats.Dot(popItemW, []float64{float64(r), 1}) +} + +func RemoveGas(args ...any) float64 { + if len(args) != 3 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + r = args[1].(int) + l = args[2].(int) + ) + if t == stackitem.MapT { + return floats.Dot(removeMapW, []float64{float64(r), float64(l), 1}) + } + return floats.Dot(removeArrayW, []float64{float64(r), 1}) +} + +func RetGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + r := args[0].(int) + s := args[1].(int) + return floats.Dot(retW, []float64{float64(r), float64(s / 100), 1}) +} + +func ReverseItemsGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + n = args[1].(int) + ) + if t == stackitem.BufferT { + return floats.Dot(reverseItemsBufferW, []float64{float64(n), 1}) + } + return floats.Dot(reverseItemsArrayW, []float64{float64(n), 1}) +} + +func ReverseGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + n := args[0].(int) + return floats.Dot(reverseW, []float64{float64(n), 1}) +} + +func RollGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + n := args[0].(int) + return floats.Dot(rollW, []float64{float64(n), 1}) +} + +func SetItemGas(args ...any) float64 { + if len(args) != 4 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + l = args[1].(int) + rRem = args[2].(int) + rAdd = args[3].(int) + ) + if t == stackitem.MapT { + return floats.Dot(setitemMapW, []float64{float64(rRem), float64(rAdd), float64(l), 1}) + } + return floats.Dot(setitemAnyW, []float64{float64(rRem), float64(rAdd), 1}) +} + +func STGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + rRem = args[0].(int) + rAdd = args[1].(int) + ) + return floats.Dot(stW, []float64{float64(rRem), float64(rAdd), 1}) +} + +func SubstrGas(args ...any) float64 { + if len(args) != 1 { + panic("invalid arg len") + } + l := args[0].(int) + return floats.Dot(substrW, []float64{float64(l), 1}) +} + +func UnpackGas(args ...any) float64 { + if len(args) != 3 { + panic("invalid arg len") + } + var ( + t = args[0].(stackitem.Type) + r = args[1].(int) + l = args[2].(int) + ) + if t == stackitem.MapT { + return floats.Dot(unpackMapW, []float64{float64(r), float64(l), 1}) + } + return floats.Dot(unpackAnyW, []float64{float64(r), float64(l), 1}) +} + +func ValuesGas(args ...any) float64 { + if len(args) != 4 { + panic("invalid arg len") + } + var ( + et = args[0].(stackitem.Type) + at = args[1].(stackitem.Type) + r = args[2].(int) + l = args[3].(int) + ) + if et == stackitem.MapT { + if at == stackitem.StructT { + return floats.Dot(valuesMapStructW, []float64{float64(r), float64(l), 1}) + } + return floats.Dot(valuesMapAnyW, []float64{float64(r), float64(l), 1}) + } + if at == stackitem.StructT { + return floats.Dot(valuesAnyStructW, []float64{float64(r), float64(l), 1}) + } + return floats.Dot(valuesAnyAnyW, []float64{float64(r), float64(l), 1}) +} + +func XDropGas(args ...any) float64 { + if len(args) != 2 { + panic("invalid arg len") + } + var ( + r = args[0].(int) + n = args[1].(int) + ) + return floats.Dot(xDropW, []float64{float64(r), float64(n), 1}) +} diff --git a/pkg/core/interop/gas_price.go b/pkg/core/interop/gas_price.go index 0a4bf92437..a40afde4a7 100644 --- a/pkg/core/interop/gas_price.go +++ b/pkg/core/interop/gas_price.go @@ -7,6 +7,12 @@ import ( // GetPrice returns a price for executing op with the provided parameter in // picoGAS units. -func (ic *Context) GetPrice(op opcode.Opcode, parameter []byte) int64 { +func (ic *Context) GetPrice(op opcode.Opcode, parameter []byte, args ...any) int64 { + if true { + if args != nil { + return fee.OpcodeDynamic(ic.baseExecFee, op, args...) + } + return fee.OpcodeStatic(ic.baseExecFee, op) + } return fee.Opcode(ic.baseExecFee, op) } diff --git a/pkg/vm/fuzz_test.go b/pkg/vm/fuzz_test.go index 7e022c2120..d1c3865390 100644 --- a/pkg/vm/fuzz_test.go +++ b/pkg/vm/fuzz_test.go @@ -36,7 +36,7 @@ func FuzzVMDontPanic(f *testing.F) { // Prevent infinite loops from being reported as fail. v.SetGasLimit(1000) - v.getPrice = func(opcode.Opcode, []byte) int64 { + v.getPrice = func(opcode.Opcode, []byte, ...any) int64 { return 1 } diff --git a/pkg/vm/opcodebench_test.go b/pkg/vm/opcodebench_test.go index 17b6523195..2359d89db9 100644 --- a/pkg/vm/opcodebench_test.go +++ b/pkg/vm/opcodebench_test.go @@ -1,8 +1,9 @@ package vm import ( - "encoding/binary" - "strconv" + "fmt" + "math" + "math/big" "testing" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -10,6 +11,14 @@ import ( "github.com/stretchr/testify/require" ) +type benchCase struct { + name string + op opcode.Opcode + params []byte + items []any + f func() *VM +} + func benchOpcodeInt(t *testing.B, f func() *VM, fail bool) { for t.Loop() { t.StopTimer() @@ -30,43 +39,20 @@ func benchOpcode(t *testing.B, f func() *VM) { benchOpcodeInt(t, f, false) } -func benchOpcodeFail(t *testing.B, f func() *VM) { - benchOpcodeInt(t, f, true) -} - -func opVM(op opcode.Opcode) func() *VM { - return opParamVM(op, nil) -} - -func opParamVM(op opcode.Opcode, param []byte) func() *VM { - return opParamPushVM(op, param) -} - -func opParamPushVM(op opcode.Opcode, param []byte, items ...any) func() *VM { - return opParamSlotsPushVM(op, param, 0, 0, 0, items...) -} - -func opParamSlotsPushVM(op opcode.Opcode, param []byte, sslot int, slotloc int, slotarg int, items ...any) func() *VM { +func opParamPushVM(bc benchCase) func() *VM { return func() *VM { - script := []byte{byte(op)} - script = append(script, param...) + script := []byte{byte(bc.op)} + script = append(script, bc.params...) v := load(script) v.SyscallHandler = func(_ *VM, _ uint32) error { return nil } - if sslot != 0 { - v.Context().sc.static.init(sslot, &v.refs) - } - if slotloc != 0 && slotarg != 0 { - v.Context().local.init(slotloc, &v.refs) - v.Context().arguments.init(slotarg, &v.refs) - } - for i := range items { - item, ok := items[i].(stackitem.Item) + for i := range bc.items { + item, ok := bc.items[i].(stackitem.Item) if ok { item = stackitem.DeepCopy(item, true) } else { - item = stackitem.Make(items[i]) + item = stackitem.Make(bc.items[i]) } v.estack.PushVal(item) } @@ -74,714 +60,1437 @@ func opParamSlotsPushVM(op opcode.Opcode, param []byte, sslot int, slotloc int, } } -func exceptParamPushVM(op opcode.Opcode, param []byte, ilen int, elen int, exception bool, items ...any) func() *VM { +func exceptParamPushVM(op opcode.Opcode, param []byte, items ...any) func() *VM { return func() *VM { - regVMF := opParamPushVM(op, param, items...) - v := regVMF() - if ilen != 0 { - eCtx := newExceptionHandlingContext(1, 2) - v.Context().tryStack.PushVal(eCtx) - for range ilen { - v.call(v.Context(), 0) - } - } else if elen != 0 { - for range elen { - eCtx := newExceptionHandlingContext(1, 2) - v.Context().tryStack.PushVal(eCtx) - } - } - if exception { - v.uncaughtException = &stackitem.Null{} - } + v := opParamPushVM(benchCase{op: op, params: param, items: items})() + v.Context().tryStack.PushVal(newExceptionHandlingContext(0, 0)) return v } } -func zeroSlice(l int) []byte { - return make([]byte, l) -} +const countPoints = 8 -func ffSlice(l int) []byte { - var s = make([]byte, l) - for i := range s { - s[i] = 0xff +func getBigInts(minBits, maxBits, num uint) []*big.Int { + var ( + step = (maxBits - minBits) / num + res = make([]*big.Int, num) + ) + res[0] = new(big.Int).Lsh(big.NewInt(1), minBits+step-1) + for i := range num { + res[i] = new(big.Int).Lsh(res[i-1], step) } - return s + return res } -func maxNumber() []byte { - s := ffSlice(32) - s[0] = 0 - return s +func getArrayWithDepth(d int) []stackitem.Item { + var item stackitem.Item = stackitem.Null{} + for range d - 1 { + item = stackitem.NewArray([]stackitem.Item{item}) + } + return []stackitem.Item{item} } -func bigNumber() []byte { - s := maxNumber() - s[31] = 0 - return s +func getStructWithDepth(d int) []stackitem.Item { + var item stackitem.Item = stackitem.Null{} + for range d - 1 { + item = stackitem.NewStruct([]stackitem.Item{item}) + } + return []stackitem.Item{item} } -func bigNegNumber() []byte { - s := ffSlice(32) - s[0] = 80 - return s +func getUniqueKeys(num, keySize int) [][]byte { + keys := make([][]byte, 0, num) + for i := range num { + key := make([]byte, keySize) + j := keySize - 1 + for i > 0 { + key[j] = byte(i & 0xff) + i >>= 8 + j-- + } + keys = append(keys, key) + } + return keys } -func arrayOfOnes(size int) []stackitem.Item { - var elems = make([]stackitem.Item, size) - for i := range elems { - elems[i] = stackitem.Make(1) +func Benchmark_IS(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepDepth = MaxStackSize / countPoints + ) + for _, op := range []opcode.Opcode{opcode.ISNULL, opcode.ISTYPE} { + currDepth := stepDepth - 1 + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", op, currDepth), + op: op, + params: []byte{0}, + items: []any{stackitem.NewArray(getArrayWithDepth(currDepth))}, + }) + currDepth += stepDepth + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) } - return elems } -func arrayOfIfaces(size int) []any { - var elems = make([]any, size) - for i := range elems { - elems[i] = 1 +func Benchmark_PUSHINT(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 6) + opToNumBytes = map[opcode.Opcode]int{ + opcode.PUSHINT8: 1, + opcode.PUSHINT16: 2, + opcode.PUSHINT32: 4, + opcode.PUSHINT64: 8, + opcode.PUSHINT128: 16, + opcode.PUSHINT256: 32, + } + ) + for op, numBytes := range opToNumBytes { + buf := make([]byte, numBytes) + buf[numBytes-1] = 0x80 + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", op, numBytes), + op: op, + params: buf, + }) + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) } - return elems } -func bigMap() *stackitem.Map { - var m = stackitem.NewMap() - for i := range 1024 { - m.Add(stackitem.Make(i), stackitem.Make(i)) +func Benchmark_PUSHDATA(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, countPoints) + stepLen = stackitem.MaxSize / countPoints + currLen = stepLen + ) + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", opcode.PUSHDATA4, currLen), + params: make([]byte, currLen), + }) + currLen += stepLen + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) } - return m } -func maxBytes() []byte { - return zeroSlice(1024 * 1024) +func Benchmark_CONVERT(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepArrayLen = MaxStackSize / countPoints + stepByteArrayLen = stackitem.MaxSize / countPoints + currArrayLen = stepArrayLen - 1 + currByteArrayLen = stepByteArrayLen + ) + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %s %d", opcode.CONVERT, stackitem.ArrayT, stackitem.StructT, currArrayLen), + params: []byte{byte(stackitem.StructT)}, + items: []any{make([]any, currArrayLen)}, + }) + currArrayLen += stepArrayLen + } + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %s %d", opcode.CONVERT, stackitem.ByteArrayT, stackitem.BufferT, currByteArrayLen), + params: []byte{byte(stackitem.BufferT)}, + items: []any{stackitem.NewByteArray(make([]byte, currByteArrayLen))}, + }) + currByteArrayLen += stepByteArrayLen + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } } -func maxBuf() *stackitem.Buffer { - return stackitem.NewBuffer(maxBytes()) +func Benchmark_INITSLOT(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 3*countPoints) + stepSlots = byte(math.MaxUint8 / countPoints) + currSlots = stepSlots + ) + for range countPoints { + for _, params := range []struct{ localSlots, argSlots byte }{ + {currSlots, 0}, + {0, currSlots}, + } { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d %d", opcode.INITSLOT, params.localSlots, params.argSlots), + op: opcode.INITSLOT, + params: []byte{params.localSlots, params.argSlots}, + items: make([]any, params.argSlots), + }) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", opcode.INITSSLOT, currSlots), + op: opcode.INITSSLOT, + params: []byte{currSlots}, + }) + currSlots += stepSlots + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } } -func BenchmarkOpcodes(t *testing.B) { - t.Run("NOP", func(t *testing.B) { benchOpcode(t, opVM(opcode.NOP)) }) - t.Run("PUSHINT8", func(t *testing.B) { - t.Run("00", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT8, []byte{0})) }) - t.Run("FF", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT8, []byte{0xff})) }) - }) - t.Run("PUSHINT16", func(t *testing.B) { - t.Run("0000", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT16, []byte{0, 0})) }) - t.Run("FFFF", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT16, []byte{0xff, 0xff})) }) - }) - t.Run("PUSHINT32", func(t *testing.B) { - t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT32, zeroSlice(4))) }) - t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT32, ffSlice(4))) }) - }) - t.Run("PUSHINT64", func(t *testing.B) { - t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT64, zeroSlice(8))) }) - t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT64, ffSlice(8))) }) - }) - t.Run("PUSHINT128", func(t *testing.B) { - t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT128, zeroSlice(16))) }) - t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT128, ffSlice(16))) }) - }) - t.Run("PUSHINT256", func(t *testing.B) { - t.Run("0000...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT256, zeroSlice(32))) }) - t.Run("FFFF...", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHINT256, ffSlice(32))) }) - }) - t.Run("PUSHA", func(t *testing.B) { - t.Run("small script", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHA, zeroSlice(4))) }) - t.Run("big script", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHA, zeroSlice(4+65536))) }) - }) - t.Run("PUSHNULL", func(t *testing.B) { benchOpcode(t, opVM(opcode.PUSHNULL)) }) - t.Run("PUSHDATA1", func(t *testing.B) { - var oneSlice = []byte{1, 0} - var maxSlice = zeroSlice(255) - maxSlice = append([]byte{255}, maxSlice...) - - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA1, oneSlice)) }) - t.Run("255", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA1, maxSlice)) }) +func Benchmark_LDSFLD(b *testing.B) { + b.Run(opcode.LDSFLD.String(), func(b *testing.B) { + benchOpcode(b, func() *VM { + v := opParamPushVM(benchCase{op: opcode.LDSFLD, params: []byte{0}})() + v.Context().sc.static = []stackitem.Item{stackitem.Null{}} + return v + }) }) - t.Run("PUSHDATA2", func(t *testing.B) { - const minLen = 256 - const maxLen = 65535 - var minSlice = zeroSlice(minLen + 2) - var maxSlice = zeroSlice(maxLen + 2) +} - binary.LittleEndian.PutUint16(minSlice, minLen) - binary.LittleEndian.PutUint16(maxSlice, maxLen) +func Benchmark_STSFLD(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepDepth = MaxStackSize / countPoints + currDepth = stepDepth + ) + for range countPoints { + for _, params := range []struct{ removedDepth, addedDepth int }{ + {currDepth, 1}, + {1, currDepth}, + } { + removedDepth := params.removedDepth + addedDepth := params.addedDepth + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d %d", opcode.STSFLD0, removedDepth, addedDepth), + f: func() *VM { + item := stackitem.NewArray(getArrayWithDepth(addedDepth - 1)) + v := opParamPushVM(benchCase{op: opcode.STSFLD0, items: []any{item}})() + slot := []stackitem.Item{stackitem.NewArray(getArrayWithDepth(removedDepth - 1))} + v.Context().sc.static = slot + v.refs.Add(slot[0]) + return v + }, + }) + } + currDepth += stepDepth + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) + }) + } +} - t.Run("256", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA2, minSlice)) }) - t.Run("65535", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA2, maxSlice)) }) - }) - t.Run("PUSHDATA4", func(t *testing.B) { - const minLen = 65536 - const maxLen = 1024 * 1024 - var minSlice = zeroSlice(minLen + 4) - var maxSlice = zeroSlice(maxLen + 4) +func Benchmark_NEW(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 5*countPoints) + //stepArrayLen = MaxStackSize / countPoints + stepByteArrayLen = stackitem.MaxSize / countPoints + //currArrayLen = stepArrayLen - 1 + currByteArrayLen = stepByteArrayLen + ) + /*for range countPoints { + for _, typ := range []stackitem.Type{stackitem.BooleanT, stackitem.IntegerT, stackitem.ByteArrayT, stackitem.AnyT} { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d", opcode.NEWARRAYT, typ, currArrayLen), + op: opcode.NEWARRAYT, + params: []byte{byte(typ)}, + items: []any{currArrayLen}, + }) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", opcode.NEWARRAY, currArrayLen), + op: opcode.NEWARRAY, + items: []any{currArrayLen}, + }) + currArrayLen += stepArrayLen + }*/ + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", opcode.NEWBUFFER, currByteArrayLen), + op: opcode.NEWBUFFER, + items: []any{currByteArrayLen}, + }) + currByteArrayLen += stepByteArrayLen + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } +} - binary.LittleEndian.PutUint32(minSlice, minLen) - binary.LittleEndian.PutUint32(maxSlice, maxLen) +func Benchmark_MEMCPY(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, countPoints) + stepByteArrayLen = stackitem.MaxSize / countPoints + currByteArrayLen = stepByteArrayLen + ) + for range countPoints { + buf1 := stackitem.NewBuffer(make([]byte, currByteArrayLen)) + buf2 := stackitem.NewBuffer(make([]byte, currByteArrayLen)) + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", opcode.MEMCPY, currByteArrayLen), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.MEMCPY})() + v.estack.PushVal(buf1) + v.estack.PushVal(0) + v.estack.PushVal(buf2) + v.estack.PushVal(0) + v.estack.PushVal(currByteArrayLen) + return v + }, + }) + currByteArrayLen += stepByteArrayLen + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) + }) + } +} - t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA4, minSlice)) }) - t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.PUSHDATA4, maxSlice)) }) - }) - t.Run("PUSHM1", func(t *testing.B) { benchOpcode(t, opVM(opcode.PUSHM1)) }) - t.Run("PUSH0", func(t *testing.B) { benchOpcode(t, opVM(opcode.PUSH0)) }) - - t.Run("JMP", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.JMP, zeroSlice(1))) }) - t.Run("JMP_L", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.JMPL, zeroSlice(4))) }) - - var jmpifs = []struct { - op opcode.Opcode - size int - }{ - {opcode.JMPIF, 1}, - {opcode.JMPIFL, 4}, - {opcode.JMPIFNOT, 1}, - {opcode.JMPIFNOTL, 4}, - } - for _, jmpif := range jmpifs { - t.Run(jmpif.op.String(), func(t *testing.B) { - t.Run("false", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpif.op, zeroSlice(jmpif.size), false)) }) - t.Run("true", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpif.op, zeroSlice(jmpif.size), true)) }) - }) - } - - var jmpcmps = []struct { - op opcode.Opcode - size int - }{ - {opcode.JMPEQ, 1}, - {opcode.JMPEQL, 4}, - {opcode.JMPNE, 1}, - {opcode.JMPNEL, 4}, - {opcode.JMPGT, 1}, - {opcode.JMPGTL, 4}, - {opcode.JMPGE, 1}, - {opcode.JMPGEL, 4}, - {opcode.JMPLT, 1}, - {opcode.JMPLTL, 4}, - {opcode.JMPLE, 1}, - {opcode.JMPLEL, 4}, - } - for _, jmpcmp := range jmpcmps { - t.Run(jmpcmp.op.String(), func(t *testing.B) { - t.Run("false", func(t *testing.B) { - t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), 1, 0)) }) - t.Run("big", func(t *testing.B) { - benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), maxNumber(), bigNumber())) - }) +func Benchmark_CAT(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, countPoints) + stepByteArrayLen = stackitem.MaxSize / countPoints + currByteArrayLen = stepByteArrayLen + ) + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", opcode.CAT, currByteArrayLen), + items: []any{ + []byte{}, + make([]byte, currByteArrayLen), + }, + }) + currByteArrayLen += stepByteArrayLen + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } +} + +func Benchmark_SUBSTR_LEFT(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepByteArrayLen = stackitem.MaxSize / countPoints + ) + for _, op := range []opcode.Opcode{opcode.SUBSTR, opcode.LEFT} { + currByteArrayLen := stepByteArrayLen + for range countPoints { + items := []any{make([]byte, currByteArrayLen)} + if op == opcode.SUBSTR { + items = append(items, 0) + } + items = append(items, currByteArrayLen) + benchCases = append(benchCases, benchCase{ + op: op, + name: fmt.Sprintf("%s %d", op, currByteArrayLen), + items: items, }) - t.Run("true", func(t *testing.B) { - t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), 1, 1)) }) - t.Run("big", func(t *testing.B) { - benchOpcode(t, opParamPushVM(jmpcmp.op, zeroSlice(jmpcmp.size), maxNumber(), maxNumber())) - }) + currByteArrayLen += stepByteArrayLen + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } +} + +func Benchmark_DROP(b *testing.B) { + /*itemsForOpcode := func(op opcode.Opcode, arr []stackitem.Item) []any { + var items []any + switch op { + case opcode.DROP, opcode.CLEAR: + items = []any{arr} + case opcode.NIP, opcode.XDROP: + items = []any{arr, 0} + default: + } + return items + }*/ + var ( + benchCases = make([]benchCase, 0, 4*countPoints) + //stepDepth = MaxStackSize / countPoints + stepStackSize = MaxStackSize / countPoints + ) + /*for _, op := range []opcode.Opcode{opcode.DROP, opcode.NIP, opcode.XDROP, opcode.CLEAR} { + currDepth := stepDepth + for range countPoints { + name := fmt.Sprintf("%s %d", op, currDepth) + switch op { + case opcode.XDROP: + name += " 0" + case opcode.CLEAR: + name += " 1" + default: + } + benchCases = append(benchCases, benchCase{ + name: name, + op: op, + items: itemsForOpcode(op, getArrayWithDepth(currDepth-1)), }) + currDepth += stepDepth + } + }*/ + for _, op := range []opcode.Opcode{opcode.XDROP /*, opcode.CLEAR*/} { + currStackSize := stepStackSize + for range countPoints { + items := make([]any, currStackSize) + items[currStackSize-1] = currStackSize - 2 + name := fmt.Sprintf("%s %d %d", op, 1, currStackSize-2) + if op == opcode.CLEAR { + name = fmt.Sprintf("%s %d %d", op, currStackSize, currStackSize) + } + benchCases = append(benchCases, benchCase{ + name: name, + op: op, + items: items, + }) + currStackSize += stepStackSize + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) } +} - t.Run("CALL", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.CALL, zeroSlice(1))) }) - t.Run("CALL_L", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.CALLL, zeroSlice(4))) }) - t.Run("CALLA", func(t *testing.B) { - t.Run("small script", func(t *testing.B) { - p := stackitem.NewPointer(0, []byte{byte(opcode.CALLA)}) - benchOpcode(t, opParamPushVM(opcode.CALLA, nil, p)) +func Benchmark_DUP(b *testing.B) { + itemsForOpcode := func(op opcode.Opcode, item any) []any { + var items []any + switch op { + case opcode.TUCK: + items = []any{nil, item} + case opcode.DUP: + items = []any{item} + case opcode.OVER, opcode.PICK: + items = []any{item, 0} + default: + } + return items + } + var ( + benchCases = make([]benchCase, 0, 4*(countPoints+1)) + stepByteArrayLen = stackitem.MaxSize / countPoints + ) + for _, op := range []opcode.Opcode{opcode.DUP, opcode.OVER, opcode.TUCK, opcode.PICK} { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s", op, stackitem.AnyT), + op: op, + items: itemsForOpcode(op, nil), }) - t.Run("big script", func(t *testing.B) { - prog := zeroSlice(65536) - prog[0] = byte(opcode.CALLA) - p := stackitem.NewPointer(0, prog) - benchOpcode(t, opParamPushVM(opcode.CALLA, zeroSlice(65535), p)) + currByteArrayLen := stepByteArrayLen + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d", op, stackitem.ByteArrayT, currByteArrayLen), + op: op, + items: itemsForOpcode(op, make([]byte, currByteArrayLen)), + }) + currByteArrayLen += stepByteArrayLen + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - }) - - t.Run("ABORT", func(t *testing.B) { benchOpcodeFail(t, opVM(opcode.ABORT)) }) - t.Run("ASSERT", func(t *testing.B) { - t.Run("true", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ASSERT, nil, true)) }) - t.Run("false", func(t *testing.B) { benchOpcodeFail(t, opParamPushVM(opcode.ASSERT, nil, false)) }) - }) + } +} - t.Run("THROW", func(t *testing.B) { - t.Run("0/1", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 0, 1, false, 1)) +func Benchmark_ROLL_REVERSE(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepStackSize = MaxStackSize / countPoints + ) + for _, op := range []opcode.Opcode{opcode.ROLL, opcode.REVERSEN} { + currStackSize := stepStackSize + for range countPoints { + var ( + items = make([]any, currStackSize) + n = currStackSize - 2 + ) + if op == opcode.REVERSEN { + n++ + } + items[currStackSize-1] = n + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", op, n), + op: op, + items: items, + }) + currStackSize += stepStackSize + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - t.Run("0/16", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 0, 16, false, 1)) + } +} + +func Benchmark_INTEGER_OPERANDS(b *testing.B) { + unaryOpcodes := []opcode.Opcode{ + opcode.INVERT, + opcode.SIGN, + opcode.ABS, + opcode.NEGATE, + opcode.INC, + opcode.DEC, + opcode.SQRT, + opcode.NZ, + } + binaryOpcodes := []opcode.Opcode{ + opcode.AND, + opcode.OR, + opcode.XOR, + opcode.EQUAL, + opcode.NOTEQUAL, + opcode.ADD, + opcode.SUB, + opcode.DIV, + opcode.MOD, + opcode.NUMEQUAL, + opcode.NUMNOTEQUAL, + opcode.LT, + opcode.LE, + opcode.GT, + opcode.GE, + opcode.MIN, + opcode.MAX, + } + ternaryOpcodes := []opcode.Opcode{ + opcode.MODMUL, + opcode.MODPOW, + } + var ( + benchCases = make([]benchCase, 0, (len(unaryOpcodes)+len(binaryOpcodes)+len(ternaryOpcodes))*countPoints) + stepNumBits = (stackitem.MaxBigIntegerSizeBits - 1) / countPoints + bigInts1 = getBigInts(0, stackitem.MaxBigIntegerSizeBits-1, countPoints) + ) + for _, op := range unaryOpcodes { + for i := range bigInts1 { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", op, bigInts1[i].BitLen()), + op: op, + items: []any{bigInts1[i]}, + }) + } + } + bigInts2 := getBigInts(0, stackitem.MaxBigIntegerSizeBits-1, countPoints) + for _, op := range binaryOpcodes { + for i := range bigInts1 { + n := bigInts2[i] + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", op, bigInts1[i].BitLen()), + op: op, + items: []any{bigInts1[i], n}, + }) + } + } + bigInts3 := getBigInts(0, stackitem.MaxBigIntegerSizeBits-1, countPoints) + for _, op := range ternaryOpcodes { + for i := range bigInts1 { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", op, bigInts1[i].BitLen()), + op: op, + items: []any{bigInts1[i], bigInts2[i], bigInts3[i]}, + }) + } + } + mulBigInts := getBigInts(0, (stackitem.MaxBigIntegerSizeBits/2)-1, countPoints) + for _, n := range mulBigInts { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", opcode.MUL, n.BitLen()), + op: opcode.MUL, + items: []any{n, n}, }) - t.Run("255/0", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 255, 0, false, 1)) + } + for _, op := range []opcode.Opcode{opcode.POW, opcode.SHL, opcode.SHR} { + currNumBits := stepNumBits + for range countPoints { + items := []any{new(big.Int).Lsh(big.NewInt(1), uint(currNumBits))} + switch op { + case opcode.POW: + items = append(items, int(math.Floor(float64(stackitem.MaxBigIntegerSizeBits)/float64(currNumBits)))) + case opcode.SHL: + items = append(items, stackitem.MaxBigIntegerSizeBits-currNumBits-2) + case opcode.SHR: + items = append(items, currNumBits) + default: + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d", op, currNumBits), + op: op, + items: items, + }) + currNumBits += stepNumBits + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - t.Run("1023/0", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.THROW, []byte{0, 0, 0, 0}, 1023, 0, false, 1)) + } +} + +func Benchmark_APPEND(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepDepth = MaxStackSize / countPoints + ) + for _, typ := range []stackitem.Type{stackitem.ArrayT, stackitem.StructT} { + currDepth := stepDepth - 1 + for range countPoints { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray(getArrayWithDepth(currDepth)) + } else { + item = stackitem.NewStruct(getStructWithDepth(currDepth)) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %s %d", opcode.APPEND, stackitem.ArrayT, typ, currDepth), + items: []any{[]any{}, item}, + }) + currDepth += stepDepth + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - }) - t.Run("TRY", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.TRY, []byte{1, 2, 0, 0})) }) - t.Run("TRY_L", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.TRYL, []byte{1, 0, 0, 0, 2, 0, 0, 0})) }) - t.Run("ENDTRY", func(t *testing.B) { - t.Run("1", func(t *testing.B) { benchOpcode(t, exceptParamPushVM(opcode.ENDTRY, []byte{0, 0, 0, 0}, 0, 1, false)) }) - t.Run("16", func(t *testing.B) { benchOpcode(t, exceptParamPushVM(opcode.ENDTRY, []byte{0, 0, 0, 0}, 0, 16, false)) }) - }) - t.Run("ENDTRY_L", func(t *testing.B) { - t.Run("1", func(t *testing.B) { benchOpcode(t, exceptParamPushVM(opcode.ENDTRYL, []byte{0, 0, 0, 0}, 0, 1, false)) }) - t.Run("16", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.ENDTRYL, []byte{0, 0, 0, 0}, 0, 16, false)) + } +} + +func Benchmark_PACKMAP(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 3*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / (2 * countPoints) + currDepth = stepDepth - 1 + ) + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.PACKMAP, stackitem.AnyT, currDepth, 1), + items: []any{stackitem.NewArray(getArrayWithDepth(currDepth - 2)), true, 1}, }) - }) - t.Run("ENDFINALLY", func(t *testing.B) { - t.Run("0/1", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 0, 1, true)) + currDepth += stepDepth + } + for _, typ := range []stackitem.Type{stackitem.IntegerT, stackitem.ByteArrayT} { + currN := stepN - 1 + for range countPoints { + items := make([]any, 0, 2*currN) + if typ == stackitem.ByteArrayT { + keys := getUniqueKeys(currN, stackitem.MaxKeySize) + for _, key := range keys { + items = append(items, nil, key) + } + } else { + for i := range 2 * currN { + items = append(items, i) + } + } + items = append(items, currN) + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.PACKMAP, typ, 2*currN, currN), + items: items, + }) + currN += stepN + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - t.Run("0/16", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 0, 16, true)) + } +} + +func Benchmark_PACK(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / countPoints + currDepth = stepDepth - 1 + currN = stepN - 1 + ) + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d %d", opcode.PACK, currDepth, 1), + items: []any{stackitem.NewArray(getArrayWithDepth(currDepth - 1)), 1}, }) - t.Run("255/0", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 255, 0, true)) + currDepth += stepDepth + } + for range countPoints { + items := make([]any, currN) + items = append(items, currN) + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d %d", opcode.PACK, currN, currN), + items: items, }) - t.Run("1023/0", func(t *testing.B) { - benchOpcode(t, exceptParamPushVM(opcode.ENDFINALLY, []byte{0, 0, 0, 0}, 1023, 0, true)) + currN += stepN + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - }) - - t.Run("RET", func(t *testing.B) { benchOpcode(t, opVM(opcode.RET)) }) - t.Run("SYSCALL", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.SYSCALL, zeroSlice(4))) }) + } +} - t.Run("DEPTH", func(t *testing.B) { - t.Run("0", func(t *testing.B) { benchOpcode(t, opVM(opcode.DEPTH)) }) - t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DEPTH, nil, arrayOfIfaces(1024)...)) }) - }) - t.Run("DROP", func(t *testing.B) { - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DROP, nil, 1)) }) - t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DEPTH, nil, arrayOfIfaces(1024)...)) }) - }) - t.Run("NIP", func(t *testing.B) { - t.Run("2", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NIP, nil, 1, 1)) }) - t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NIP, nil, arrayOfIfaces(1024)...)) }) - }) - t.Run("XDROP", func(t *testing.B) { - t.Run("0/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, 0, 0)) }) - var items = arrayOfIfaces(1025) - items[1024] = 0 - t.Run("0/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, items...)) }) - items[1024] = 1023 - t.Run("1024/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, items...)) }) - items = arrayOfIfaces(2048) - items[2047] = 2046 - t.Run("2047/2048", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.XDROP, nil, items...)) }) - }) - t.Run("CLEAR", func(t *testing.B) { - t.Run("0", func(t *testing.B) { benchOpcode(t, opVM(opcode.CLEAR)) }) - t.Run("1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEAR, nil, arrayOfIfaces(1024)...)) }) - t.Run("2048", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEAR, nil, arrayOfIfaces(2048)...)) }) - }) - var copiers = []struct { - op opcode.Opcode - pos int - l int - }{ - {opcode.DUP, 0, 1}, - {opcode.OVER, 1, 2}, - {opcode.PICK, 2, 3}, - {opcode.PICK, 1024, 1025}, - {opcode.TUCK, 1, 2}, - } - for _, cp := range copiers { - var name = cp.op.String() - if cp.op == opcode.PICK { - name += "/" + strconv.Itoa(cp.pos) - } - var getitems = func(element any) []any { - l := cp.l - pos := cp.pos - if cp.op == opcode.PICK { - pos++ - l++ - } - var items = make([]any, l) - for i := range items { - items[i] = 0 - } - items[pos] = element - if cp.op == opcode.PICK { - items[0] = cp.pos +func Benchmark_UNPACK(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 4*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / countPoints + ) + for _, typ := range []stackitem.Type{stackitem.ArrayT, stackitem.MapT} { + currDepth := stepDepth - 1 + for range countPoints { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray(getArrayWithDepth(currDepth)) + } else { + item = stackitem.NewMapWithValue([]stackitem.MapElement{{ + Key: stackitem.NewBool(true), + Value: stackitem.NewArray(getArrayWithDepth(currDepth - 2)), + }}) } - return items - } - t.Run(name, func(t *testing.B) { - t.Run("null", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.Null{})...)) }) - t.Run("boolean", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(true)...)) }) - t.Run("integer", func(t *testing.B) { - t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(1)...)) }) - t.Run("big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(bigNumber())...)) }) + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.UNPACK, typ, currDepth, 1), + items: []any{item}, }) - t.Run("bytearray", func(t *testing.B) { - t.Run("small", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems("01234567")...)) }) - t.Run("big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(zeroSlice(65536))...)) }) + currDepth += stepDepth + } + currN := stepN - 1 + for range countPoints { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray(make([]stackitem.Item, currN)) + } else { + var ( + keys = getUniqueKeys(currN/2, stackitem.MaxKeySize) + m = make([]stackitem.MapElement, 0, currN/2) + ) + for _, key := range keys { + m = append(m, stackitem.MapElement{Key: stackitem.NewByteArray(key)}) + } + item = stackitem.NewMapWithValue(m) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.UNPACK, typ, currN, currN), + items: []any{item}, }) - t.Run("buffer", func(t *testing.B) { - t.Run("small", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewBuffer(zeroSlice(1)))...)) - }) - t.Run("big", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewBuffer(zeroSlice(65536)))...)) + currN += stepN + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } +} + +func Benchmark_PICKITEM(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 5*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / (2 * countPoints) + stepByteArrayLen = stackitem.MaxSize / countPoints + ) + for _, typ := range []stackitem.Type{stackitem.ArrayT, stackitem.MapT} { + currDepth := stepDepth - 1 + for range countPoints { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray([]stackitem.Item{ + stackitem.NewArray(getArrayWithDepth(currDepth)), }) + } else { + item = stackitem.NewMapWithValue([]stackitem.MapElement{{ + Key: stackitem.NewBigInteger(big.NewInt(0)), + Value: stackitem.NewArray(getArrayWithDepth(currDepth)), + }}) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d %s", opcode.PICKITEM, typ, currDepth, 1, stackitem.ArrayT), + items: []any{item, 0}, }) - t.Run("struct", func(t *testing.B) { - var items = make([]stackitem.Item, 1) - t.Run("small", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewStruct(items))...)) - }) - // Stack overflow. - if cp.op == opcode.PICK && cp.pos == 1024 { - return + currDepth += stepDepth + } + if typ == stackitem.MapT { + currN := stepN - 1 + for range countPoints { + keys := getUniqueKeys(currN, stackitem.MaxKeySize) + m := make([]stackitem.MapElement, 0, currN) + for _, key := range keys { + m = append(m, stackitem.MapElement{Key: stackitem.NewByteArray(key)}) } - items = make([]stackitem.Item, 1024) - t.Run("big", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(stackitem.NewStruct(items))...)) + m[currN-1].Value = stackitem.Null{} + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d %s", opcode.PICKITEM, typ, 1, currN, stackitem.AnyT), + items: []any{stackitem.NewMapWithValue(m), keys[currN-1]}, + }) + currN += stepN + } + } + currByteArrayLen := stepByteArrayLen - 1 + for range countPoints { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray([]stackitem.Item{ + stackitem.NewByteArray(make([]byte, currByteArrayLen)), + }) + } else { + item = stackitem.NewMapWithValue([]stackitem.MapElement{ + { + Key: stackitem.NewBigInteger(big.NewInt(0)), + Value: stackitem.NewByteArray(make([]byte, currByteArrayLen)), + }, }) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d %s %d", opcode.PICKITEM, typ, 1, 1, stackitem.ByteArrayT, currByteArrayLen), + items: []any{item, 0}, }) - p := stackitem.NewPointer(0, zeroSlice(1024)) - t.Run("pointer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DUP, nil, getitems(p)...)) }) - }) - } - - var swappers = []struct { - op opcode.Opcode - num int - }{ - {opcode.SWAP, 2}, - {opcode.ROT, 3}, - {opcode.ROLL, 4}, - {opcode.ROLL, 1024}, - {opcode.REVERSE3, 3}, - {opcode.REVERSE4, 4}, - {opcode.REVERSEN, 5}, - {opcode.REVERSEN, 1024}, - } - for _, sw := range swappers { - var name = sw.op.String() - if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { - name += "/" + strconv.Itoa(sw.num) - } - var getitems = func(element any) []any { - l := sw.num - if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { - l++ + currByteArrayLen += stepByteArrayLen + } + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d %s", opcode.PICKITEM, stackitem.ByteArrayT, 1, 1, stackitem.IntegerT), + items: []any{[]byte{42}, 0}, + }) + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } +} + +func Benchmark_SETITEM(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 5*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / (2 * countPoints) + ) + for _, typ := range []stackitem.Type{stackitem.ArrayT, stackitem.MapT} { + currDepth := stepDepth - 1 + for range countPoints { + for _, params := range []struct{ removedDepth, addedDepth int }{ + {currDepth, 1}, + {1, currDepth}, + } { + removedDepth := params.removedDepth + addedDepth := params.addedDepth + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d %d", opcode.SETITEM, typ, removedDepth, addedDepth, 1), + f: func() *VM { + var item, addedItem stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray(getArrayWithDepth(removedDepth)) + addedItem = stackitem.NewArray(getArrayWithDepth(addedDepth - 1)) + } else { + item = stackitem.NewMapWithValue([]stackitem.MapElement{ + { + Key: stackitem.NewBigInteger(big.NewInt(0)), + Value: stackitem.NewArray(getArrayWithDepth(removedDepth - 2)), + }, + }) + addedItem = stackitem.NewArray(getArrayWithDepth(addedDepth - 2)) + } + v := opParamPushVM(benchCase{op: opcode.SETITEM})() + v.estack.PushVal(item) + v.estack.PushVal(0) + v.estack.PushVal(addedItem) + return v + }, + }) } - var items = make([]any, l) - for i := range items { - items[i] = element + currDepth += stepDepth + } + if typ == stackitem.MapT { + currN := stepN - 1 + for range countPoints { + n := currN + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d %d", opcode.SETITEM, typ, 1, 1, currN), + f: func() *VM { + keys := getUniqueKeys(n, stackitem.MaxKeySize) + m := make([]stackitem.MapElement, 0, n) + for _, key := range keys { + m = append(m, stackitem.MapElement{Key: stackitem.NewByteArray(key)}) + } + m[n-1].Value = stackitem.Null{} + v := opParamPushVM(benchCase{op: opcode.SETITEM})() + v.estack.PushVal(stackitem.NewMapWithValue(m)) + v.estack.PushVal(keys[n-1]) + v.estack.PushVal(stackitem.Null{}) + return v + }, + }) + currN += stepN } - if sw.op == opcode.ROLL || sw.op == opcode.REVERSEN { - items[len(items)-1] = sw.num - 1 + } + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s", opcode.SETITEM, stackitem.BufferT), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.SETITEM})() + v.estack.PushVal(stackitem.NewBuffer([]byte{42})) + v.estack.PushVal(0) + v.estack.PushVal(42) + return v + }, + }) + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) + }) + } +} + +func Benchmark_REVERSEITEMS(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepArrayLen = MaxStackSize / countPoints + stepByteArrayLen = stackitem.MaxSize / countPoints + currArrayLen = stepArrayLen + currByteArrayLen = stepByteArrayLen + ) + for range countPoints { + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d", opcode.REVERSEITEMS, stackitem.ArrayT, currArrayLen), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.REVERSEITEMS})() + v.estack.PushVal(make([]any, currArrayLen)) + return v + }, + }) + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d", opcode.REVERSEITEMS, stackitem.BufferT, currByteArrayLen), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.REVERSEITEMS})() + v.estack.PushVal(stackitem.NewBuffer(make([]byte, currByteArrayLen))) + return v + }, + }) + currArrayLen += stepArrayLen + currByteArrayLen += stepByteArrayLen + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) + }) + } +} + +func Benchmark_REMOVE(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 3*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / (2 * countPoints) + ) + for _, typ := range []stackitem.Type{stackitem.ArrayT, stackitem.MapT} { + currDepth := stepDepth - 1 + for range countPoints { + depth := currDepth + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.REMOVE, typ, depth, 1), + f: func() *VM { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray(getArrayWithDepth(depth)) + } else { + item = stackitem.NewMapWithValue([]stackitem.MapElement{ + { + Key: stackitem.NewBigInteger(big.NewInt(0)), + Value: stackitem.NewArray(getArrayWithDepth(depth - 2)), + }, + }) + } + v := opParamPushVM(benchCase{op: opcode.REMOVE})() + v.estack.PushVal(item) + v.estack.PushVal(0) + return v + }, + }) + currDepth += stepDepth + } + if typ == stackitem.MapT { + currN := stepN - 1 + for range countPoints { + n := currN + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.REMOVE, typ, 1, currN), + f: func() *VM { + keys := getUniqueKeys(n, stackitem.MaxKeySize) + m := make([]stackitem.MapElement, 0, n) + for _, key := range keys { + m = append(m, stackitem.MapElement{Key: stackitem.NewByteArray(key)}) + } + m[n-1].Value = stackitem.Null{} + v := opParamPushVM(benchCase{op: opcode.REMOVE})() + v.estack.PushVal(stackitem.NewMapWithValue(m)) + v.estack.PushVal(keys[n-1]) + return v + }, + }) + currN += stepN } - return items } - t.Run(name, func(t *testing.B) { - t.Run("null", func(t *testing.B) { - benchOpcode(t, opParamPushVM(sw.op, nil, getitems(stackitem.Null{})...)) + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) + }) + } +} + +func Benchmark_CLEARITEMS(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 4*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / countPoints + ) + for _, typ := range []stackitem.Type{stackitem.ArrayT, stackitem.MapT} { + currDepth := stepDepth - 1 + for range countPoints { + depth := currDepth + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.CLEARITEMS, typ, depth, 1), + f: func() *VM { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray(getArrayWithDepth(depth)) + } else { + item = stackitem.NewMapWithValue([]stackitem.MapElement{ + { + Key: stackitem.NewBigInteger(big.NewInt(0)), + Value: stackitem.NewArray(getArrayWithDepth(depth - 2)), + }, + }) + } + v := opParamPushVM(benchCase{op: opcode.CLEARITEMS})() + v.estack.PushVal(item) + return v + }, }) - t.Run("integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(sw.op, nil, getitems(0)...)) }) - t.Run("big bytes", func(t *testing.B) { - benchOpcode(t, opParamPushVM(sw.op, nil, getitems(zeroSlice(65536))...)) + currDepth += stepDepth + } + currN := stepN - 1 + for range countPoints { + n := currN + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %d", opcode.CLEARITEMS, typ, 1, n), + f: func() *VM { + var item stackitem.Item + if typ == stackitem.ArrayT { + item = stackitem.NewArray(make([]stackitem.Item, n)) + } else { + m := make([]stackitem.MapElement, 0, n/2) + for i := range n / 2 { + m = append(m, stackitem.MapElement{ + Key: stackitem.NewBigInteger(big.NewInt(int64(i))), + Value: stackitem.Null{}, + }) + } + item = stackitem.NewMapWithValue(m) + } + v := opParamPushVM(benchCase{op: opcode.CLEARITEMS})() + v.estack.PushVal(item) + return v + }, }) + currN += stepN + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) }) } +} - t.Run("INITSSLOT", func(t *testing.B) { - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.INITSSLOT, []byte{1})) }) - t.Run("255", func(t *testing.B) { benchOpcode(t, opParamVM(opcode.INITSSLOT, []byte{255})) }) - }) - t.Run("INITSLOT", func(t *testing.B) { - t.Run("1/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{1, 1}, 0)) }) - t.Run("1/255", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{1, 255}, arrayOfIfaces(255)...)) - }) - t.Run("255/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{255, 1}, 0)) }) - t.Run("255/255", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.INITSLOT, []byte{255, 255}, arrayOfIfaces(255)...)) +func Benchmark_POPITEM(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, countPoints) + stepDepth = MaxStackSize / countPoints + currDepth = stepDepth - 1 + ) + for range countPoints { + depth := currDepth + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d", opcode.POPITEM, stackitem.ArrayT, depth), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.POPITEM})() + v.estack.PushVal(stackitem.NewArray(getArrayWithDepth(depth))) + return v + }, }) - }) - t.Run("LDSFLD0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDSFLD0, nil, 1, 0, 0)) }) - t.Run("LDSFLD254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDSFLD, []byte{254}, 255, 0, 0)) }) - t.Run("STSFLD0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STSFLD0, nil, 1, 0, 0, 0)) }) - t.Run("STSFLD254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STSFLD, []byte{254}, 255, 0, 0, 0)) }) - t.Run("LDLOC0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDLOC0, nil, 0, 1, 1)) }) - t.Run("LDLOC254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDLOC, []byte{254}, 0, 255, 255)) }) - t.Run("STLOC0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STLOC0, nil, 0, 1, 1, 0)) }) - t.Run("STLOC254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STLOC, []byte{254}, 0, 255, 255, 0)) }) - t.Run("LDARG0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDARG0, nil, 0, 1, 1)) }) - t.Run("LDARG254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.LDARG, []byte{254}, 0, 255, 255)) }) - t.Run("STARG0", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STARG0, nil, 0, 1, 1, 0)) }) - t.Run("STARG254", func(t *testing.B) { benchOpcode(t, opParamSlotsPushVM(opcode.STARG, []byte{254}, 0, 255, 255, 0)) }) - - t.Run("NEWBUFFER", func(t *testing.B) { - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 1)) }) - t.Run("255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 255)) }) - t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 65536)) }) - t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWBUFFER, nil, 1024*1024)) }) - }) - t.Run("MEMCPY", func(t *testing.B) { - buf1 := maxBuf() - buf2 := maxBuf() - - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 1)) }) - t.Run("255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 255)) }) - t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 65536)) }) - t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MEMCPY, nil, buf1, 0, buf2, 0, 1024*1024)) }) - }) - t.Run("CAT", func(t *testing.B) { - t.Run("1+1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(1), zeroSlice(1))) }) - t.Run("256+256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(255), zeroSlice(255))) }) - t.Run("64K+64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(65536), zeroSlice(65536))) }) - t.Run("512K+512K", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.CAT, nil, zeroSlice(512*1024), zeroSlice(512*1024))) + currDepth += stepDepth + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) }) - }) - t.Run("SUBSTR", func(t *testing.B) { - buf := stackitem.NewBuffer(zeroSlice(1024 * 1024)) + } +} - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 1)) }) - t.Run("256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 256)) }) - t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 65536)) }) - t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SUBSTR, nil, buf, 0, 1024*1024)) }) - }) - t.Run("LEFT", func(t *testing.B) { - buf := stackitem.NewBuffer(zeroSlice(1024 * 1024)) +func Benchmark_SIZE(b *testing.B) { + benchCases := []benchCase{ + { + name: fmt.Sprintf("%s %s", opcode.SIZE, stackitem.ArrayT), + items: []any{[]any{}}, + }, + { + name: fmt.Sprintf("%s %s", opcode.SIZE, stackitem.MapT), + items: []any{stackitem.NewMap()}, + }, + { + name: fmt.Sprintf("%s %s", opcode.SIZE, stackitem.ByteArrayT), + items: []any{[]byte{}}, + }, + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } +} - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 1)) }) - t.Run("256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 256)) }) - t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 65536)) }) - t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.LEFT, nil, buf, 1024*1024)) }) - }) - t.Run("RIGHT", func(t *testing.B) { - buf := stackitem.NewBuffer(zeroSlice(1024 * 1024)) +func Benchmark_JUMP(b *testing.B) { + benchCases := []benchCase{ + { + op: opcode.JMP, + params: []byte{0}, + }, + { + op: opcode.JMPIF, + params: []byte{0}, + items: []any{true}, + }, + { + op: opcode.JMPEQ, + params: []byte{0}, + items: []any{0, 0}, + }, + } + for _, bc := range benchCases { + b.Run(bc.op.String(), func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) + }) + } +} - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 1)) }) - t.Run("256", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 256)) }) - t.Run("64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 65536)) }) - t.Run("1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.RIGHT, nil, buf, 1024*1024)) }) - }) - unaries := []opcode.Opcode{opcode.INVERT, opcode.SIGN, opcode.ABS, opcode.NEGATE, opcode.INC, opcode.DEC, opcode.NOT, opcode.NZ} - for _, op := range unaries { - t.Run(op.String(), func(t *testing.B) { - t.Run("1", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1)) }) - t.Run("0", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 0)) }) - t.Run("big", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber())) }) - t.Run("big negative", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNegNumber())) }) - }) - } - binaries := []opcode.Opcode{opcode.AND, opcode.OR, opcode.XOR, opcode.ADD, opcode.SUB, - opcode.BOOLAND, opcode.BOOLOR, opcode.NUMEQUAL, opcode.NUMNOTEQUAL, - opcode.LT, opcode.LE, opcode.GT, opcode.GE, opcode.MIN, opcode.MAX} - for _, op := range binaries { - t.Run(op.String(), func(t *testing.B) { - t.Run("0+0", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 0, 0)) }) - t.Run("1+1", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1, 1)) }) - t.Run("1/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1, bigNumber())) }) - t.Run("big/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber(), bigNumber())) }) - t.Run("big/bigneg", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber(), bigNegNumber())) }) - }) - } - equals := []opcode.Opcode{opcode.EQUAL, opcode.NOTEQUAL} - for _, op := range equals { - t.Run(op.String(), func(t *testing.B) { - t.Run("bools", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, true, false)) }) - t.Run("small integers", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, 1, 0)) }) - t.Run("big integers", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, bigNumber(), bigNegNumber())) }) - t.Run("255B", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, zeroSlice(255), zeroSlice(255))) }) - t.Run("64KEQ", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, zeroSlice(65535), zeroSlice(65535))) }) - t.Run("64KNEQ", func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, zeroSlice(65535), ffSlice(65535))) }) - }) - } - t.Run(opcode.MUL.String(), func(t *testing.B) { - t.Run("1+0", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MUL, nil, 1, 0)) }) - t.Run("100/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MUL, nil, 100, bigNumber())) }) - t.Run("16ff*16ff", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MUL, nil, ffSlice(16), ffSlice(16))) }) - }) - t.Run(opcode.DIV.String(), func(t *testing.B) { - t.Run("0/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DIV, nil, 0, 1)) }) - t.Run("big/100", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DIV, nil, bigNumber(), 100)) }) - t.Run("bigneg/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.DIV, nil, bigNumber(), bigNegNumber())) }) - }) - t.Run(opcode.MOD.String(), func(t *testing.B) { - t.Run("1+1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MOD, nil, 1, 1)) }) - t.Run("big/100", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MOD, nil, bigNumber(), 100)) }) - t.Run("big/bigneg", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.MOD, nil, bigNumber(), bigNegNumber())) }) - }) - t.Run(opcode.SHL.String(), func(t *testing.B) { - t.Run("1/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, 1, 1)) }) - t.Run("1/254", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, 1, 254)) }) - t.Run("big/7", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, bigNumber(), 7)) }) - t.Run("bigneg/7", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, bigNegNumber(), 7)) }) - t.Run("16ff/15", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHL, nil, ffSlice(16), 15)) }) - }) - t.Run(opcode.SHR.String(), func(t *testing.B) { - t.Run("1/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, 1, 1)) }) - t.Run("1/254", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, 1, 254)) }) - t.Run("big/254", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, bigNumber(), 254)) }) - t.Run("bigneg/7", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, bigNegNumber(), 7)) }) - t.Run("16ff/15", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SHR, nil, ffSlice(16), 15)) }) - }) - t.Run(opcode.WITHIN.String(), func(t *testing.B) { - t.Run("0/1/2", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.WITHIN, nil, 1, 0, 2)) }) - t.Run("bigNeg/1/big", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.WITHIN, nil, 1, bigNegNumber(), bigNumber())) }) - t.Run("bigNeg/big/max", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.WITHIN, nil, bigNumber(), bigNegNumber(), maxNumber())) +func Benchmark_CALL(b *testing.B) { + benchCases := []benchCase{ + { + name: opcode.CALL.String(), + f: func() *VM { + return opParamPushVM(benchCase{op: opcode.CALL, params: []byte{0}})() + }, + }, + { + name: opcode.CALLA.String(), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.CALLA})() + p := stackitem.NewPointerWithHash(0, []byte{42}, v.Context().ScriptHash()) + v.estack.PushVal(p) + return v + }, + }, + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) }) - }) - var newrefs = []opcode.Opcode{opcode.NEWARRAY0, opcode.NEWSTRUCT0, opcode.NEWMAP} - for _, op := range newrefs { - t.Run(op.String(), func(t *testing.B) { benchOpcode(t, opVM(op)) }) - } - var newcountedrefs = []opcode.Opcode{opcode.NEWARRAY, opcode.NEWSTRUCT} - for _, op := range newcountedrefs { - var nums = []int{1, 255, 1024} - t.Run(op.String(), func(t *testing.B) { - for _, n := range nums { - t.Run(strconv.Itoa(n), func(t *testing.B) { benchOpcode(t, opParamPushVM(op, nil, n)) }) + } +} + +func Benchmark_KEYS(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepMapLen = MaxStackSize / (2 * countPoints) + ) + for _, typ := range []stackitem.Type{stackitem.IntegerT, stackitem.ByteArrayT} { + currMapLen := stepMapLen - 1 + for range countPoints { + m := make([]stackitem.MapElement, 0, currMapLen) + if typ == stackitem.IntegerT { + for i := range currMapLen { + m = append(m, stackitem.MapElement{Key: stackitem.NewBigInteger(big.NewInt(int64(i)))}) + } + } else { + keys := getUniqueKeys(currMapLen, stackitem.MaxKeySize) + for _, key := range keys { + m = append(m, stackitem.MapElement{Key: stackitem.NewByteArray(key)}) + } } + benchCases = append(benchCases, benchCase{ + op: opcode.KEYS, + name: fmt.Sprintf("%s %s %d", opcode.KEYS, typ, currMapLen), + items: []any{stackitem.NewMapWithValue(m)}, + }) + currMapLen += stepMapLen + } + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) } - t.Run("NEWARRAYT", func(t *testing.B) { - var nums = []int{1, 255, 1024} - var types = []stackitem.Type{stackitem.AnyT, stackitem.PointerT, stackitem.BooleanT, - stackitem.IntegerT, stackitem.ByteArrayT, stackitem.BufferT, stackitem.ArrayT, - stackitem.StructT, stackitem.MapT, stackitem.InteropT} - for _, n := range nums { - for _, typ := range types { - t.Run(typ.String()+"/"+strconv.Itoa(n), func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.NEWARRAYT, []byte{byte(typ)}, n)) }) +} + +func Benchmark_VALUES(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 6*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / countPoints + ) + for _, itemTyp := range []stackitem.Type{stackitem.ArrayT, stackitem.MapT} { + for _, clonedTyp := range []stackitem.Type{stackitem.AnyT, stackitem.StructT} { + currDepth := stepDepth - 1 + for range countPoints { + var item, clonedItem stackitem.Item + if clonedTyp == stackitem.StructT { + clonedItem = stackitem.NewStruct(getStructWithDepth(currDepth - 1)) + } else { + clonedItem = stackitem.NewArray(getArrayWithDepth(currDepth - 1)) + } + if itemTyp == stackitem.ArrayT { + item = stackitem.NewArray([]stackitem.Item{clonedItem}) + } else { + item = stackitem.NewMapWithValue([]stackitem.MapElement{ + { + Key: stackitem.NewBool(true), + Value: clonedItem, + }, + }) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %s %d %d", opcode.VALUES, itemTyp, clonedTyp, currDepth, 1), + items: []any{item}, + }) + currDepth += stepDepth } } - }) - t.Run("PACK", func(t *testing.B) { - var nums = []int{1, 255, 1024} - for _, n := range nums { - t.Run(strconv.Itoa(n), func(t *testing.B) { - var elems = make([]any, n+1) - for i := range elems { - elems[i] = 0 + currN := stepN - 1 + for range countPoints { + var ( + item stackitem.Item + n int + ) + if itemTyp == stackitem.ArrayT { + n = currN + arr := make([]stackitem.Item, 0, currN) + for range currN { + arr = append(arr, stackitem.Null{}) } - elems[n] = n - benchOpcode(t, opParamPushVM(opcode.PACK, nil, elems...)) - }) - } - }) - t.Run("UNPACK", func(t *testing.B) { - var nums = []int{1, 255, 1024} - for _, n := range nums { - t.Run(strconv.Itoa(n), func(t *testing.B) { - var elems = make([]stackitem.Item, n) - for i := range elems { - elems[i] = stackitem.Make(1) + item = stackitem.NewArray(arr) + } else { + n = currN / 2 + m := make([]stackitem.MapElement, 0, currN/2) + for i := range currN / 2 { + m = append(m, stackitem.MapElement{ + Key: stackitem.NewBigInteger(big.NewInt(int64(i))), + Value: stackitem.Null{}, + }) } - benchOpcode(t, opParamPushVM(opcode.UNPACK, nil, elems)) + item = stackitem.NewMapWithValue(m) + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %s %d %d", opcode.VALUES, itemTyp, stackitem.AnyT, n, n), + items: []any{item}, }) + currN += stepN } - }) - t.Run("SIZE", func(t *testing.B) { - var elems = arrayOfOnes(1024) - var buf = maxBytes() - t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, elems[:1])) }) - t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, elems)) }) - t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, bigMap())) }) - t.Run("bytes/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, buf[:255])) }) - t.Run("bytes/64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, buf[:65536])) }) - t.Run("bytes/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SIZE, nil, buf)) }) - }) - t.Run("HASKEY", func(t *testing.B) { - var elems = arrayOfOnes(1024) - var buf = maxBuf() - t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, elems, 1)) }) - t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, elems, 1023)) }) - t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, elems, 1024)) }) - t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, bigMap(), 1)) }) - t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, bigMap(), 1023)) }) - t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, bigMap(), 1024)) }) - t.Run("buffer/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, buf, 255)) }) - t.Run("buffer/64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, buf, 65536)) }) - t.Run("buffer/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.HASKEY, nil, buf, 1024*1024)) }) - }) - t.Run("KEYS", func(t *testing.B) { - t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.KEYS, nil, bigMap())) }) - }) - t.Run("VALUES", func(t *testing.B) { - var elems = arrayOfOnes(1024) - t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.VALUES, nil, elems[:1])) }) - t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.VALUES, nil, elems)) }) - t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.VALUES, nil, bigMap())) }) - }) - t.Run("PICKITEM", func(t *testing.B) { - var elems = arrayOfOnes(1024) - var buf = maxBytes() - t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, elems, 1)) }) - t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, elems, 1023)) }) - t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, bigMap(), 1)) }) - t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, bigMap(), 1023)) }) - t.Run("bytes/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, buf, 255)) }) - t.Run("bytes/64K", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, buf, 65536)) }) - t.Run("bytes/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.PICKITEM, nil, buf, 1024*1024-1)) }) - }) - t.Run("APPEND", func(t *testing.B) { - var a0 = arrayOfOnes(0) - var a1023 = arrayOfOnes(1023) - t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, a0, 1)) }) - t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, a1023, 1)) }) - t.Run("struct/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, stackitem.NewStruct(a0), 1)) }) - t.Run("struct/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.APPEND, nil, stackitem.NewStruct(a1023), 1)) }) - t.Run("array/struct", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.APPEND, nil, a1023, stackitem.NewStruct(a1023))) + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - }) - t.Run("SETITEM", func(t *testing.B) { - var elems = arrayOfOnes(1024) - var buf = maxBuf() - t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, elems, 1, 1)) }) - t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, elems, 1023, 1)) }) - t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, bigMap(), 1, 1)) }) - t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, bigMap(), 1023, 1)) }) - t.Run("buffer/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, buf, 255, 1)) }) - t.Run("buffer/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.SETITEM, nil, buf, 1024*1024-1, 1)) }) - }) + } +} - t.Run("REVERSEITEMS", func(t *testing.B) { - var elems = arrayOfOnes(1024) - var buf = maxBuf() - t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REVERSEITEMS, nil, elems)) }) - t.Run("buffer/1M", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REVERSEITEMS, nil, buf)) }) - }) +func Benchmark_RET(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints) + stepDepth = MaxStackSize / countPoints + stepN = MaxStackSize / countPoints + currDepth = stepDepth + currN = stepN + ) + for range countPoints { + depth := currDepth + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d %d", opcode.RET, depth, 1), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.RET})() + callerCtx := &Context{retCount: 1, sc: &scriptContext{estack: NewStack("call")}} + callerCtx.sc.estack.PushVal(stackitem.NewArray(getArrayWithDepth(depth - 1))) + v.istack = append(v.istack, callerCtx) + v.estack = callerCtx.Estack() + return v + }, + }) + currDepth += stepDepth + } + for range countPoints { + n := currN + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %d %d", opcode.RET, n, n), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.RET})() + callerCtx := &Context{retCount: n, sc: &scriptContext{estack: NewStack("call")}} + for range n { + callerCtx.sc.estack.PushVal(stackitem.Null{}) + } + v.istack = append(v.istack, callerCtx) + v.estack = callerCtx.Estack() + return v + }, + }) + currN += stepN + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) + }) + } +} - t.Run("REMOVE", func(t *testing.B) { - var elems = arrayOfOnes(1024) - t.Run("array/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, elems, 1)) }) - t.Run("array/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, elems, 255)) }) - t.Run("array/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, elems, 1023)) }) - t.Run("map/1", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, bigMap(), 1)) }) - t.Run("map/255", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, bigMap(), 255)) }) - t.Run("map/1023", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.REMOVE, nil, bigMap(), 1023)) }) - }) - t.Run("CLEARITEMS", func(t *testing.B) { - t.Run("array/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEARITEMS, nil, arrayOfOnes(1024))) }) - t.Run("map/1024", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.CLEARITEMS, nil, bigMap())) }) +func Benchmark_HASKEY(b *testing.B) { + var ( + benchCases = make([]benchCase, 0, 2*countPoints+2) + stepN = MaxStackSize / (2 * countPoints) + ) + for _, typ := range []stackitem.Type{stackitem.IntegerT, stackitem.ByteArrayT} { + currN := stepN - 1 + for range countPoints { + m := make([]stackitem.MapElement, 0, currN) + if typ == stackitem.IntegerT { + for i := range currN { + m = append(m, stackitem.MapElement{Key: stackitem.Make(i)}) + } + } else { + keys := getUniqueKeys(currN, stackitem.MaxKeySize) + for _, key := range keys { + m = append(m, stackitem.MapElement{Key: stackitem.NewByteArray(key)}) + } + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s %d %s", opcode.HASKEY, stackitem.MapT, currN, typ), + items: []any{stackitem.NewMapWithValue(m), m[currN-1].Key}, + }) + currN += stepN + } + } + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s", opcode.HASKEY, stackitem.ArrayT), + items: []any{[]any{}, 0}, }) - - t.Run("ISNULL", func(t *testing.B) { - t.Run("null", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISNULL, nil, stackitem.Null{})) }) - t.Run("integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISNULL, nil, 1)) }) + benchCases = append(benchCases, benchCase{ + name: fmt.Sprintf("%s %s", opcode.HASKEY, stackitem.ByteArrayT), + items: []any{[]byte{}, 0}, }) - t.Run("ISTYPE", func(t *testing.B) { - t.Run("null/null", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.ISTYPE, []byte{byte(stackitem.AnyT)}, stackitem.Null{})) + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, opParamPushVM(bc)) }) - t.Run("integer/integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISTYPE, []byte{byte(stackitem.IntegerT)}, 1)) }) - t.Run("null/integer", func(t *testing.B) { benchOpcode(t, opParamPushVM(opcode.ISTYPE, []byte{byte(stackitem.AnyT)}, 1)) }) - }) - t.Run("CONVERT", func(t *testing.B) { - t.Run("bytes/integer", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.CONVERT, []byte{byte(stackitem.IntegerT)}, "1012345678901234567890123456789")) + } +} + +func Benchmark_THROW_ABORT(b *testing.B) { + benchCases := []benchCase{ + { + name: opcode.THROW.String(), + op: opcode.THROW, + items: []any{"error"}, + }, + { + name: opcode.ABORT.String(), + op: opcode.ABORT, + }, + { + name: opcode.ABORTMSG.String(), + op: opcode.ABORTMSG, + items: []any{"error"}, + }, + { + name: opcode.ASSERT.String(), + op: opcode.ASSERT, + items: []any{false}, + }, + { + name: opcode.ASSERTMSG.String(), + op: opcode.ASSERTMSG, + items: []any{false, "error"}, + }, + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, exceptParamPushVM(bc.op, nil, bc.items...)) }) - t.Run("integer/bytes", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.CONVERT, []byte{byte(stackitem.ByteArrayT)}, maxNumber())) + } +} + +func Benchmark_TRY(b *testing.B) { + benchCases := []benchCase{ + { + name: opcode.TRY.String(), + f: func() *VM { + return opParamPushVM(benchCase{op: opcode.TRY, params: []byte{1, 0}})() + }, + }, + { + name: opcode.ENDTRY.String(), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.ENDTRY, params: []byte{0}})() + v.Context().tryStack.PushVal(newExceptionHandlingContext(0, -1)) + return v + }, + }, + { + name: opcode.ENDFINALLY.String(), + f: func() *VM { + v := opParamPushVM(benchCase{op: opcode.ENDFINALLY})() + v.Context().tryStack.PushVal(&exceptionHandlingContext{EndOffset: 0}) + return v + }, + }, + } + for _, bc := range benchCases { + b.Run(bc.name, func(b *testing.B) { + benchOpcode(b, bc.f) }) - t.Run("array/struct", func(t *testing.B) { - benchOpcode(t, opParamPushVM(opcode.CONVERT, []byte{byte(stackitem.StructT)}, arrayOfOnes(1024))) + } +} + +func Benchmark_OPCODES_WITHOUT_ANYTHING(b *testing.B) { + opcodes := []opcode.Opcode{ + opcode.PUSHM1, + opcode.PUSH0, + opcode.PUSHT, + opcode.PUSHNULL, + opcode.NEWMAP, + opcode.NOP, + } + for _, op := range opcodes { + b.Run(op.String(), func(b *testing.B) { + benchOpcode(b, opParamPushVM(benchCase{op: op})) }) - }) + } } diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 92bd818bc4..adf3bac5f9 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -12,6 +12,7 @@ import ( "os" "slices" "text/tabwriter" + "time" "unicode/utf8" "github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames" @@ -79,7 +80,7 @@ type VM struct { state vmstate.State // callback to get interop price - getPrice func(opcode.Opcode, []byte) int64 + getPrice func(opcode.Opcode, []byte, ...any) int64 istack []*Context // invocation stack. estack *Stack // execution stack. @@ -146,7 +147,7 @@ func (v *VM) SetOnExecHook(hook OnExecHook) { // SetPriceGetter registers the given PriceGetterFunc in v. // f accepts vm's Context, current instruction and instruction parameter. -func (v *VM) SetPriceGetter(f func(opcode.Opcode, []byte) int64) { +func (v *VM) SetPriceGetter(f func(opcode.Opcode, []byte, ...any) int64) { v.getPrice = f } @@ -508,6 +509,11 @@ func (v *VM) Ready() bool { return len(v.istack) > 0 } +type S struct { + gas, count int64 + ns *big.Int +} + // Run starts execution of the loaded program. func (v *VM) Run() error { var ctx *Context @@ -525,6 +531,9 @@ func (v *VM) Run() error { // vmstate.Halt (the default) or vmstate.Break are safe to continue. v.state = vmstate.None ctx = v.Context() + v.SetGasLimit(15 * 10_000_000) + m := make(map[opcode.Opcode]*S) + s := time.Now() for { switch { case v.state.HasFlag(vmstate.Fault): @@ -535,9 +544,42 @@ func (v *VM) Run() error { // Normal exit from this loop. return nil case v.state == vmstate.None: + op := opcode.Opcode(ctx.sc.prog[ctx.IP()]) + prevGas := v.gasConsumed + start := time.Now() if err := v.step(ctx); err != nil { + dur := time.Since(s) + var ( + totalCount int64 + totalNS = new(big.Int) + ) + for _, s := range m { + totalCount += s.count + totalNS.Add(totalNS, s.ns) + } + for op, s := range m { + /*f, _ := new(big.Rat).SetFrac(s.ns, totalNS).Float64() + fmt.Printf("%s gas: %.6f, ns: %.6f, count: %.6f\n", + op, float64(s.gas)/float64(v.gasConsumed), f, float64(s.count)/float64(totalCount), + )*/ + f, _ := new(big.Rat).SetFrac(s.ns, big.NewInt(s.count)).Float64() + fmt.Printf("%s ns: %.6f, count: %d\n", op, f, s.count) + } + fmt.Printf("%.6f\n\n", dur.Seconds()) + //fmt.Printf("totalGas: %d, totalNS: %s, totalCount: %d\n\n", v.gasConsumed, totalNS, totalCount) + /*dur := time.Since(start) + fmt.Printf("%.6f\n\n", dur.Seconds())*/ return err } + dur := time.Since(start) + if v.gasConsumed != prevGas { + if m[op] == nil { + m[op] = &S{ns: new(big.Int)} + } + m[op].count++ + //m[op].gas += v.gasConsumed - prevGas + m[op].ns.Add(m[op].ns, big.NewInt(dur.Nanoseconds())) + } default: v.state = vmstate.Fault return errors.New("unknown state") @@ -677,23 +719,22 @@ func GetInteropID(parameter []byte) uint32 { func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err error) { // Instead of polluting the whole VM logic with error handling, we will recover // each panic at a central point, putting the VM in a fault state and setting error. - defer func() { + var args []any + defer func(canGetPrice bool) { + if canGetPrice { + v.gasConsumed += v.getPrice(op, parameter, args...) + } if errRecover := recover(); errRecover != nil { v.state = vmstate.Fault err = newError(ctx.IP(), op, errRecover) } else if v.refs > MaxStackSize { v.state = vmstate.Fault err = newError(ctx.IP(), op, fmt.Sprintf("stack is too big: %d vs %d", int(v.refs), MaxStackSize)) + } else if v.gasLimit >= 0 && v.gasConsumed > v.gasLimit { + v.state = vmstate.Fault + err = newError(ctx.IP(), op, "gas limit is exceeded") } - }() - - if v.getPrice != nil && ctx.IP() < len(ctx.sc.prog) && !ctx.sc.whitelisted { - p := v.getPrice(op, parameter) - v.gasConsumed += p - if v.gasLimit >= 0 && v.gasConsumed > v.gasLimit { - panic("gas limit is exceeded") - } - } + }(v.getPrice != nil && ctx.IP() < len(ctx.sc.prog) && !ctx.sc.whitelisted) if op <= opcode.PUSHINT256 { v.estack.PushItem(stackitem.NewBigInteger(bigint.FromBytes(parameter))) @@ -732,19 +773,26 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro v.estack.PushItem(stackitem.Bool(res.Type() == stackitem.Type(parameter[0]))) case opcode.CONVERT: - typ := stackitem.Type(parameter[0]) + fromTyp := stackitem.Type(parameter[0]) item := v.estack.Pop().Item() - result, err := item.Convert(typ) + result, err := item.Convert(fromTyp) if err != nil { panic(err) } v.estack.PushItem(result) + toTyp := item.Type() + if fromTyp == stackitem.ArrayT && toTyp == stackitem.StructT || fromTyp == stackitem.StructT && toTyp == stackitem.ArrayT { + args = []any{fromTyp, len(item.Value().([]stackitem.Item))} + } else if fromTyp == stackitem.ByteArrayT && toTyp == stackitem.BufferT { + args = []any{fromTyp, len(item.Value().([]byte))} + } case opcode.INITSSLOT: if parameter[0] == 0 { panic("zero argument") } ctx.sc.static.init(int(parameter[0]), &v.refs) + args = []any{parameter[0], byte(0)} case opcode.INITSLOT: if ctx.local != nil || ctx.arguments != nil { @@ -763,6 +811,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro ctx.arguments.set(i, v.estack.Pop().Item(), &v.refs) } } + args = []any{parameter[0], parameter[1]} case opcode.LDSFLD0, opcode.LDSFLD1, opcode.LDSFLD2, opcode.LDSFLD3, opcode.LDSFLD4, opcode.LDSFLD5, opcode.LDSFLD6: item := ctx.sc.static.Get(int(op - opcode.LDSFLD0)) @@ -773,12 +822,18 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro v.estack.PushItem(item) case opcode.STSFLD0, opcode.STSFLD1, opcode.STSFLD2, opcode.STSFLD3, opcode.STSFLD4, opcode.STSFLD5, opcode.STSFLD6: + beforePop := v.refs item := v.estack.Pop().Item() + beforeRem := v.refs ctx.sc.static.set(int(op-opcode.STSFLD0), item, &v.refs) + args = []any{int(beforePop - v.refs), int(beforePop - beforeRem)} case opcode.STSFLD: + beforePop := v.refs item := v.estack.Pop().Item() + beforeRem := v.refs ctx.sc.static.set(int(parameter[0]), item, &v.refs) + args = []any{int(beforePop - v.refs), int(beforePop - beforeRem)} case opcode.LDLOC0, opcode.LDLOC1, opcode.LDLOC2, opcode.LDLOC3, opcode.LDLOC4, opcode.LDLOC5, opcode.LDLOC6: item := ctx.local.Get(int(op - opcode.LDLOC0)) @@ -789,12 +844,18 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro v.estack.PushItem(item) case opcode.STLOC0, opcode.STLOC1, opcode.STLOC2, opcode.STLOC3, opcode.STLOC4, opcode.STLOC5, opcode.STLOC6: + beforePop := v.refs item := v.estack.Pop().Item() + beforeRem := v.refs ctx.local.set(int(op-opcode.STLOC0), item, &v.refs) + args = []any{int(beforePop - v.refs), int(beforePop - beforeRem)} case opcode.STLOC: + beforePop := v.refs item := v.estack.Pop().Item() + beforeRem := v.refs ctx.local.set(int(parameter[0]), item, &v.refs) + args = []any{int(beforePop - v.refs), int(beforePop - beforeRem)} case opcode.LDARG0, opcode.LDARG1, opcode.LDARG2, opcode.LDARG3, opcode.LDARG4, opcode.LDARG5, opcode.LDARG6: item := ctx.arguments.Get(int(op - opcode.LDARG0)) @@ -805,12 +866,18 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro v.estack.PushItem(item) case opcode.STARG0, opcode.STARG1, opcode.STARG2, opcode.STARG3, opcode.STARG4, opcode.STARG5, opcode.STARG6: + beforePop := v.refs item := v.estack.Pop().Item() + beforeRem := v.refs ctx.arguments.set(int(op-opcode.STARG0), item, &v.refs) + args = []any{int(beforePop - v.refs), int(beforePop - beforeRem)} case opcode.STARG: + beforePop := v.refs item := v.estack.Pop().Item() + beforeRem := v.refs ctx.arguments.set(int(parameter[0]), item, &v.refs) + args = []any{int(beforePop - v.refs), int(beforePop - beforeRem)} case opcode.NEWBUFFER: n := toInt(v.estack.Pop().BigInt()) @@ -818,6 +885,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic("invalid size") } v.estack.PushItem(stackitem.NewBuffer(make([]byte, n))) + args = []any{n} case opcode.MEMCPY: n := toInt(v.estack.Pop().BigInt()) @@ -841,6 +909,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic("size is too big") } copy(dst[di:], src[si:si+n]) + args = []any{n} case opcode.CAT: b := v.estack.Pop().Bytes() @@ -853,6 +922,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro copy(ab, a) copy(ab[len(a):], b) v.estack.PushItem(stackitem.NewBuffer(ab)) + args = []any{l} case opcode.SUBSTR: l := toInt(v.estack.Pop().BigInt()) @@ -871,6 +941,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro res := make([]byte, l) copy(res, s[o:last]) v.estack.PushItem(stackitem.NewBuffer(res)) + args = []any{l} case opcode.LEFT: l := toInt(v.estack.Pop().BigInt()) @@ -884,6 +955,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro res := make([]byte, l) copy(res, s[:l]) v.estack.PushItem(stackitem.NewBuffer(res)) + args = []any{l} case opcode.RIGHT: l := toInt(v.estack.Pop().BigInt()) @@ -894,6 +966,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro res := make([]byte, l) copy(res, s[len(s)-l:]) v.estack.PushItem(stackitem.NewBuffer(res)) + args = []any{l} case opcode.DEPTH: v.estack.PushItem(stackitem.NewBigInteger(big.NewInt(int64(v.estack.Len())))) @@ -902,13 +975,17 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if v.estack.Len() < 1 { panic("stack is too small") } + r := v.refs v.estack.Pop() + args = []any{int(r - v.refs)} case opcode.NIP: if v.estack.Len() < 2 { panic("no second element found") } + r := v.refs _ = v.estack.RemoveAt(1) + args = []any{int(r - v.refs)} case opcode.XDROP: n := toInt(v.estack.Pop().BigInt()) @@ -918,13 +995,21 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if v.estack.Len() < n+1 { panic("bad index") } + r := v.refs _ = v.estack.RemoveAt(n) + args = []any{int(r - v.refs), n} case opcode.CLEAR: + r := v.refs + l := v.estack.Len() v.estack.Clear() + args = []any{int(r - v.refs), l} case opcode.DUP: v.estack.Push(v.estack.Dup(0)) + if elem := v.estack.Peek(0); elem.value.Type() == stackitem.ByteArrayT { + args = []any{len(elem.value.Value().([]byte))} + } case opcode.OVER: if v.estack.Len() < 2 { @@ -932,6 +1017,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } a := v.estack.Dup(1) v.estack.Push(a) + if a.value.Type() == stackitem.ByteArrayT { + args = []any{len(a.value.Value().([]byte))} + } case opcode.PICK: n := toInt(v.estack.Pop().BigInt()) @@ -943,6 +1031,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } a := v.estack.Dup(n) v.estack.Push(a) + if a.value.Type() == stackitem.ByteArrayT { + args = []any{len(a.value.Value().([]byte))} + } case opcode.TUCK: if v.estack.Len() < 2 { @@ -950,6 +1041,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } a := v.estack.Dup(0) v.estack.InsertAt(a, 2) + if a.value.Type() == stackitem.ByteArrayT { + args = []any{len(a.value.Value().([]byte))} + } case opcode.SWAP: err := v.estack.Swap(1, 0) @@ -969,6 +1063,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if err != nil { panic(err.Error()) } + args = []any{n} case opcode.REVERSE3, opcode.REVERSE4, opcode.REVERSEN: n := 3 @@ -982,6 +1077,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if err := v.estack.ReverseTop(n); err != nil { panic(err.Error()) } + args = []any{n} // Bit operations. case opcode.INVERT: @@ -1242,6 +1338,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro res = stackitem.NewArray(items) } v.estack.PushItem(res) + args = []any{typ, n} case opcode.NEWSTRUCT0: v.estack.PushItem(stackitem.NewStruct([]stackitem.Item{})) @@ -1261,7 +1358,13 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic("APPEND: not of underlying type Array") } + typ := stackitem.AnyT + if _, ok := itemElem.value.(*stackitem.Struct); ok { + typ = stackitem.StructT + } + prevRefs := v.refs v.refs.Add(val) + args = []any{typ, int(v.refs - prevRefs)} case opcode.PACKMAP: n := toInt(v.estack.Pop().BigInt()) @@ -1278,7 +1381,11 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } m.Add(key.value, val) } + r := v.refs v.estack.PushItem(m) + if n > 0 { + args = []any{m.Value().([]stackitem.MapElement)[0].Key.Type(), int(v.refs - r), n * n} + } case opcode.PACKSTRUCT, opcode.PACK: n := toInt(v.estack.Pop().BigInt()) @@ -1297,12 +1404,15 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } else { res = stackitem.NewStruct(items) } + r := v.refs v.estack.PushItem(res) + args = []any{int(v.refs - r), n} case opcode.UNPACK: e := v.estack.Pop() var arr []stackitem.Item var l int + r := v.refs switch t := e.value.(type) { case *stackitem.Array: @@ -1326,12 +1436,17 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } } v.estack.PushItem(stackitem.NewBigInteger(big.NewInt(int64(l)))) + args = []any{e.value.Type(), int(v.refs - r), l} case opcode.PICKITEM: key := v.estack.Pop() validateMapKey(key) - obj := v.estack.Pop() + var ( + obj = v.estack.Pop() + item stackitem.Item + l int + ) switch t := obj.value.(type) { // Struct and Array items have their underlying value as []Item. @@ -1343,15 +1458,16 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro v.throw(stackitem.NewByteArray([]byte(msg))) return } - item := arr[index].Dup() - v.estack.PushItem(item) + item = arr[index].Dup() case *stackitem.Map: index := t.Index(key.Item()) if index < 0 { v.throw(stackitem.NewByteArray([]byte("Key not found in Map"))) return } - v.estack.PushItem(t.Value().([]stackitem.MapElement)[index].Value.Dup()) + m := t.Value().([]stackitem.MapElement) + l = len(m) + item = m[index].Value.Dup() default: index := toInt(key.BigInt()) arr := obj.Bytes() @@ -1360,16 +1476,26 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro v.throw(stackitem.NewByteArray([]byte(msg))) return } - item := arr[index] - v.estack.PushItem(stackitem.NewBigInteger(big.NewInt(int64(item)))) + item = stackitem.NewBigInteger(big.NewInt(int64(arr[index]))) + } + r := v.refs + v.estack.PushItem(item) + n := int(v.refs - r) + if item.Type() == stackitem.ByteArrayT { + n = len(item.Value().([]byte)) } + args = []any{obj.Item().Type(), item.Type(), l, n} case opcode.SETITEM: item := v.estack.Pop().value key := v.estack.Pop() validateMapKey(key) - obj := v.estack.Pop() + var ( + obj = v.estack.Pop() + beforeRemove, beforeAdd refCounter + l int + ) switch t := obj.value.(type) { // Struct and Array items have their underlying value as []Item. @@ -1384,16 +1510,23 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if t.(stackitem.Immutable).IsReadOnly() { panic(stackitem.ErrReadOnly) } + beforeRemove = v.refs v.refs.Remove(arr[index]) arr[index] = item + beforeAdd = v.refs v.refs.Add(arr[index]) case *stackitem.Map: if t.IsReadOnly() { panic(stackitem.ErrReadOnly) } + l = t.Len() if i := t.Index(key.value); i >= 0 { + beforeRemove = v.refs v.refs.Remove(t.Value().([]stackitem.MapElement)[i].Value) + beforeAdd = v.refs } else { + beforeRemove = v.refs + beforeAdd = v.refs v.refs.Add(key.value) } t.Add(key.value, item) @@ -1412,30 +1545,45 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic("invalid value") } t.Value().([]byte)[index] = byte(b) + beforeRemove = v.refs + beforeAdd = v.refs default: panic(fmt.Sprintf("SETITEM: invalid item type %s", t)) } + args = []any{obj.value.Type(), l, int(beforeAdd - beforeRemove), int(v.refs - beforeAdd)} case opcode.REVERSEITEMS: - item := v.estack.Pop() + var ( + item = v.estack.Pop() + n int + ) switch t := item.value.(type) { case *stackitem.Array, *stackitem.Struct: if t.(stackitem.Immutable).IsReadOnly() { panic(stackitem.ErrReadOnly) } - slices.Reverse(t.Value().([]stackitem.Item)) + arr := t.Value().([]stackitem.Item) + n = len(arr) + slices.Reverse(arr) case *stackitem.Buffer: b := t.Value().([]byte) + n = len(b) slices.Reverse(b) default: panic(fmt.Sprintf("invalid item type %s", t)) } + args = []any{item.value.Type(), n} + case opcode.REMOVE: key := v.estack.Pop() validateMapKey(key) - elem := v.estack.Pop() + var ( + elem = v.estack.Pop() + r = v.refs + l int + ) switch t := elem.value.(type) { case *stackitem.Array: a := t.Value().([]stackitem.Item) @@ -1460,6 +1608,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro // No error on missing key. if index >= 0 { elems := t.Value().([]stackitem.MapElement) + l = len(elems) key := elems[index].Key val := elems[index].Value t.Drop(index) @@ -1469,15 +1618,23 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro default: panic("REMOVE: invalid type") } + args = []any{elem.Item().Type(), int(r - v.refs), l} case opcode.CLEARITEMS: - elem := v.estack.Pop() + var ( + elem = v.estack.Pop() + r refCounter + l int + ) switch t := elem.value.(type) { case *stackitem.Array: if t.IsReadOnly() { panic(stackitem.ErrReadOnly) } - for _, item := range t.Value().([]stackitem.Item) { + arr := t.Value().([]stackitem.Item) + r = v.refs + l = len(arr) + for _, item := range arr { v.refs.Remove(item) } t.Clear() @@ -1485,7 +1642,10 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro if t.IsReadOnly() { panic(stackitem.ErrReadOnly) } - for _, item := range t.Value().([]stackitem.Item) { + arr := t.Value().([]stackitem.Item) + r = v.refs + l = len(arr) + for _, item := range arr { v.refs.Remove(item) } t.Clear() @@ -1494,6 +1654,8 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic(stackitem.ErrReadOnly) } elems := t.Value().([]stackitem.MapElement) + r = v.refs + l = 2 * len(elems) for i := range elems { v.refs.Remove(elems[i].Key) v.refs.Remove(elems[i].Value) @@ -1502,12 +1664,14 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro default: panic("CLEARITEMS: invalid type") } + args = []any{int(r - v.refs), l} case opcode.POPITEM: arr := v.estack.Pop().Item() elems := arr.Value().([]stackitem.Item) index := len(elems) - 1 elem := elems[index] + r := v.refs v.estack.PushItem(elem) // push item on stack firstly, to match the reference behaviour. switch item := arr.(type) { case *stackitem.Array: @@ -1515,6 +1679,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro case *stackitem.Struct: item.Remove(index) } + args = []any{int(v.refs - r)} case opcode.SIZE: elem := v.estack.Pop() @@ -1601,12 +1766,17 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro panic(fmt.Errorf("invalid return values count: expected %d, got %d", oldCtx.retCount, oldEstack.Len())) } - rvcount := oldEstack.Len() + var ( + rvcount = oldEstack.Len() + refCount = oldEstack.refs + stackSize = oldEstack.Len() + ) for i := rvcount; i > 0; i-- { elem := oldEstack.RemoveAt(i - 1) newEstack.Push(elem) } v.estack = newEstack + args = []any{int(*refCount), stackSize * stackSize} } case opcode.NEWMAP: @@ -1628,6 +1798,9 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro arr = append(arr, m.Value().([]stackitem.MapElement)[k].Key.Dup()) } v.estack.PushItem(stackitem.NewArray(arr)) + if m.Len() != 0 { + args = []any{m.Value().([]stackitem.MapElement)[0].Key.Type(), m.Len()} + } case opcode.VALUES: if v.estack.Len() == 0 { @@ -1651,8 +1824,11 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro default: panic("not a Map, Array or Struct") } - + r := v.refs v.estack.PushItem(stackitem.NewArray(arr)) + if len(arr) > 0 { + args = []any{item.value.Type(), arr[0].Type(), int(v.refs - r), len(arr)} + } case opcode.HASKEY: if v.estack.Len() < 2 { @@ -1672,6 +1848,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro res = index < len(c.Array()) case *stackitem.Map: res = t.Has(key.Item()) + args = []any{key.Item().Type(), t.Len()} case *stackitem.Buffer, *stackitem.ByteArray: index := toInt(key.BigInt()) if index < 0 { diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index f01e180300..51063f846c 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -68,7 +68,7 @@ func TestVM_SetPriceGetter(t *testing.T) { require.EqualValues(t, 0, v.GasConsumed()) }) - v.SetPriceGetter(func(op opcode.Opcode, p []byte) int64 { + v.SetPriceGetter(func(op opcode.Opcode, p []byte, args ...any) int64 { if op == opcode.PUSH4 { return 1 * ExecFeeFactorMultiplier } else if op == opcode.PUSHDATA1 && bytes.Equal(p, []byte{0xCA, 0xFE}) {