大量(1秒あたり〜50,000リクエスト)Java web-app私はThreadLocalを使用して、リクエストスコープごとに実行する必要があるタスクを実行しています。
私はSpringリクエストスコープを使用して同じ効果を達成することができ、どちらの方がパフォーマンスが良いのか疑問に思いましたか?
コードでは、ThreadLocalを使用します。
private static final ThreadLocal<SomeClass> myThreadLocal = new ThreadLocal<SomeClass>();
そして、各httpリクエスト設定について:
myThreadLocal.set(new SomeClass());
Springリクエストスコープの使用:
@Component
@Scope("request")
public class SomeClass{
...
}
今、何がもっと費用がかかります:
myThreadLocal.get();
OR
SpringContext.getBean(SomeClass.class);
誰かがすでにそのようなベンチマークを試したことがあるのだろうか?
従来のJava=アプローチを考えると、答えは非常に遅いので以下の引用から差し引くことができます。
リフレクションには動的に解決されるタイプが含まれるため、特定のJava仮想マシンの最適化は実行できません。そのため、リフレクト操作は非リフレクト操作よりもパフォーマンスが遅いため、コードのセクションでは避ける必要がありますこれは、パフォーマンスに敏感なアプリケーションで頻繁に呼び出されます。
リフレクションに関するJavaDocからの引用- http://Java.Sun.com/docs/books/tutorial/reflect/index.html
したがって、SpringはgetBean()
でReflectionを使用するため、メソッドSpringContext.getBean(SomeClass.class);
アプローチは遅くなるはずです。
[〜#〜]編集[〜#〜]:
また、ThreadLocal
にもcaching embeddedが含まれているため、これらのスレッドで情報を再利用する限り、確実に高速になります。
ThreadLocal
ソリューションに関して、おそらくWebサーバーにスレッドプールがあり(例:Tomcat)、スレッドローカル変数は、各要求が処理スレッドとして完了すると実際にはクリアされないことを追加したいと思います。スレッドプールを有効にした状態で死なないでください。
各リクエストの完了時に、スレッドローカル変数(threadLocal.remove()
)を手動でクリアする必要があります。たとえば、Springのリクエスト/レスポンスインターセプターのいくつかのafterCompletion()
を使用できます。
Springソリューションはコストがかかるになりますが、コードがよりきれいなIMOになります。 Beanのフェッチ、作成、初期化、および格納には、多くの手順が含まれます。ただし、ThreadLocal
のようにリクエストスコープBeanをクリアすることを考える必要はありません。対応するServletRequest
がクリーンアップされるときに収集されます。