問題タブ [escape-analysis]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - Java 手動スタック割り当て
私は Java に比較的慣れていないので、ウィキペディアのエスケープ解析に関する非常に興味深い記事を読んだところです。ただし、スタック割り当てが使用されると言及されているのは、オブジェクトがメソッド呼び出しをエスケープしない場合だけです。これは多少制限されているようです。しかし、繰り返しになりますが、オブジェクトをスタックに割り当てたいと思うことは他にありません。だから私は疑問に思っています:
1) オブジェクトをスタックに割り当てることが理にかなっている場合は他にありますか?
2) オブジェクトをヒープではなくスタックに手動で割り当てる方法はありますか?
2.5) 存在する場合、(メソッドをエスケープしないオブジェクトの場合) エスケープ解析を行う代わりに、それを実行する方が速くなりますか? または、「このメソッドでは、すべてのオブジェクトがヒープ上にある必要があります。スタック上にある可能性があるかどうかを気にしないでください」のようなJavaに伝える方法はありますか?
ありがとう!
java - JVM は有効期間の短いオブジェクトの作成を省略できるので、パフォーマンスを損なうことなくリファクタリングを行うことができますか?
アルゴリズムの過程で、互いに依存する、または互いに離れて意味をなさないいくつかの値を計算するか、単に保存する必要がある場合があります。
(非常に無意味ですが、重要なことは単純な)例と同じようint[]
に、 number に最も近いで 2 つの異なる値を見つけることができます3
。
との計算は相互に依存するため、メソッドcomputeA()
とcomputeB()
を同じクラスで作成することはできません。だから、コンピューティングとは、別のクラスにリファクタリングされることを求めているだけです:a
b
a
b
したがって、より高いレベルのコードは素晴らしく明確になります。
ただし(間違っている場合は修正してください)、少なくともいくつかのレベルの最適化、インスタンス化、および新しいオブジェクトのガベージコレクション(edenからだけですが、とにかく)を導入します。コード。また、スタックで int を探すと、ヒープでオブジェクトを探すことになります。
ここでの質問は次のとおりです。JVM は、最終的にリファクタリングされたコードを最適化して、リファクタリングされていないコードと同じように動作するほど十分にスマートですか?
よりクリーンなコードのためにいくつかの変数を新しいオブジェクトにまとめたい別のケースは、の呼び出しに固有のデータを保持a()
する新しいクラスを導入することにより、長いメソッドをいくつかの新しいメソッドにリファクタリングしたい場合です。そのデータを操作するためのいくつかの新しいメソッド。新しいリンク (ノードのペア) を追加できる一連のチェーンを表すクラスを実装して、既存のチェーンを拡張したり、2 つのチェーンを 1 つに結合したり、2 つのノードの新しいチェーンを作成したりするときに、このようなケースに出くわしました。いくつかの観点から、その特定のクラスについて説明しましょう。C
a()
addLink
のいくつかのメソッドに適切に分割するにはSetOfChains
、これらの新しいメソッドのそれぞれに多くのパラメータが必要です。addLink()
これは、 のすべてのステップで必要な呼び出しに固有のデータがあるためですaddLink()
。そのデータを の専用フィールドに保存することSetOfChains
も可能ですが、臭くて表現力に欠けます (メソッドの呼び出し中にのみ意味があるため)。したがって、明らかに、そのデータをそのフィールドに保持する新しい内部クラスを作成し、すべてのアルゴリズム手順を実行します。 、chains
リファクタリングされてaddLink()
いないものと同じように外部フィールドを変更します。
しかし、機能的には、古い長い unrefactored を持つことと同等であるためaddLink()
、JVM は結果の命令を、あたかもLinkAddition
オブジェクトが存在しないかのように、リファクタリングされていない場合と同じくらい最適にすることができますか?
では、そのテキストの壁の下に結論を下すと、データとメソッドをメソッドではなく新しいクラスに抽出することで、コードを理解しやすくしようとすると、必然的にパフォーマンスが低下するのでしょうか?
そして、記述されたケースがまさに逃亡分析の対象であるということを正しく理解していますか?
java - 分析の疑いを逃れる
エスケープ分析 (Java 8、64 ビット サーバー JVM) を少し試してみようと思いました。私はこの本当にばかげた「アプリケーション」を思いつきました。そこでは、多くの Address オブジェクトを作成します (郵便番号、通り、国、およびオブジェクトが生成されたタイムスタンプで構成されます)。また、Address には isOk() メソッドがあり、それを返しますタイムスタンプが 7 で割り切れる場合は true...)。
プログラムは次のとおりです。
これまでのところ、jVisualVM でプロファイリングしましたが、実行中にヒープに Address オブジェクトはありません。アプリケーション全体が数秒で完了します。
ただし、次のようにリファクタリングすると:
Baaang、エスケープ分析はありません。すべての Address オブジェクトは、重いガベージ コレクション サイクルでヒープに割り当てられてしまいます。なぜそうなのですか?つまり、Address インスタンスはどちらの方法でもエスケープしません (2 番目のバージョンでは、Address オブジェクトのスコープはさらに狭くなり、for ループ ブロックでさえメソッドをエスケープしません)。
java - javaエスケープ解析は、要素が1つしかない配列でも機能しますか?
バックグラウンド:
長いコード片からメソッドを抽出すると、プリミティブ変数で値渡しの問題に遭遇することがよくあります。呼び出し元が変更を確認できるように、抽出されたメソッドでこれらのプリミティブ パラメーターを変更することはできません。プリミティブ変数を要素が 1 つだけの配列にすることで、これを回避できます。次に、参照渡しで効果的に使用されます。ただし、現在はヒープ上のオブジェクトです。Java のエスケープ解析は、それを理解して、それにもかかわらずスタックを使用するほど賢いのでしょうか?
次のコードとケースを指定すると、インライン化できませんでした:
go - スタック割り当てに関してGoで「小さな」オブジェクトと見なされるものは何ですか?
コード:
次に実行go build -gcflags='-m' . 2>&1
して、メモリ割り当ての詳細を確認します。結果:
私の質問は、なぜa
小さいオブジェクトで、b
大きいオブジェクトなのですか?
make
64KB がヒープにエスケープされ、それ以下がスタックに割り当てられます。が_MaxSmallSize = 32 << 10
理由でしょうか?
go env