プログラミングにおけるメモリ管理は無関係な関心事になっていますか?


38

背景
私は、昔から行ったことのない古い(しかし素晴らしい)サイトであるAlioth Language Shootout(http://benchmarksgame.alioth.debian.org/)を再訪しました。

私は数年前にC / C ++でプログラミングを開始しましたが、それ以来、関与しているプロジェクトの言語の制約のため、ほぼJavaのみで作業を続けてきました。リソース使用量の点でC / C ++に反しました。

実行時間は最悪で、JavaはC / C ++よりも4倍も遅いを実行すると、まだ比較的良好であったが、平均の周りの(または以下)2倍に。Java自体の実装の性質により、これは驚くことではなく、パフォーマンス時間は実際に私が予想したものよりも短かったです。

実際のレンガはメモリ割り当てでした-最悪の場合、Javaが割り当てられました:

  • Cの52倍ものメモリ
  • C ++の25倍以上。

メモリの52倍...絶対に厄介ですよね?... またはそれは?現在、メモリは比較的安価です。

質問:
作業メモリに厳しい制限があるターゲットプラットフォーム(つまり、組み込みシステムなど)に関して話さない場合、今日汎用言語を選択する際にメモリ使用量を考慮する必要がありますか?

第一言語としてScalaへの移行を検討しているからです。私はそれの機能面が非常に好きですが、私が見ることができることから、それはJavaよりもメモリの点でさらに高価です。ただし、メモリは年々速く、安く、豊富になっているようです(少なくとも4GBのDDR3 RAMを持たない消費者のラップトップを見つけることはますます困難になっているようです)。より読みやすいソリューションを迅速に構築できる(おそらく実装上高価な)高レベル言語機能と比較して無関係ですか?


32
Javaが小さなベンチマークでCの52倍のメモリを割り当てるからといって、大規模なアプリケーションで52倍のメモリを使用するわけではないことを忘れないでください。そのメモリの大部分はJVMが必要とする固定量であり、アプリケーションが大きくなればなるほど、その部分はそれほど重要ではなくなります。
-Carson63000

4
はい、モバイル開発が関係ない場合。
ジェフ

3
問題は、JavaベンチマークとC / C ++がどれほど悪いのか、そして2つの言語を選択するという意味では何を意味するのかということです。これはトピックに沿ったものであり、すべてのプログラマーに関連し、明確で、集中しており、現在の形式で合理的に答えられるものだと思います。再開することに投票しました。
グレンペターソン

ほとんどのパフォーマンスの問題は、ツールレベルではなく、デザインレベルで発生し、修正されます。一部の問題には1msの粒度が必要であるため、C / C ++が必要です。10ミリ秒などの余裕がある場合は、おそらくScalaまたはJavaが適切なオプションです。ゲーム用のほとんどの入力コントローラーは50〜100msレベルで動作します。今日、多くの人々が重要なセクションをある言語で書き、プログラムの残りの部分を別の言語で書きます。
グレンペターソン

4
このテストで「C ++よりも25倍」を調べる場合、ランタイムの継続的な追加(約13 Mb)を考慮する必要があります。問題が大きくなると、実行時のメモリ要件はプログラム全体の割合として少なくなります。C ++のメモリ使用量が1 MB未満の場合、Javaのメモリ使用量からC ++のメモリ使用量を引くと、ほぼ一定の値が得られます。

回答:


34

メモリ管理は、何かが大量のメモリを持っている場合でも、どれだけ速く表示されるかを管理するため、まったく関連しています。最良かつ最も標準的な例は、Call of DutyやBioshockのようなAAAタイトルのゲームです。これらは、最適化と使用の観点から大量の制御を必要とする事実上リアルタイムのアプリケーションです。問題は使用法そのものではなく、管理です。

ガベージコレクションという2つの言葉になります。ガベージコレクションアルゴリズムは、パフォーマンスのわずかな中断を引き起こしたり、アプリケーションを1、2秒ハングさせたりすることがあります。会計アプリではほとんど無害ですが、Call of Dutyのゲームでのユーザーエクスペリエンスの点では潜在的に破滅的です。したがって、時間が重要なアプリケーションでは、ガベージコレクションされた言語は非常に問題になる可能性があります。たとえば、Squirrelの設計目標の1つです。Squirrelは、代わりに参照カウントを使用して、LuaがGCで抱えている問題を解決しようとしています。

それは頭痛の種ですか?もちろん、正確な制御が必要な場合は、我慢してください。


14
-1 "...ゲームで文字通り致命的..."-私の日課は、生命の安全のように安全性が重要なシステムです。ゲームソフトウェアで起こる最悪の事態は、作家が破産し、誰もそれを買わないため破産することです。これは些細なことではない違いです。
マッテンツ

4
@mattnz私の言葉の選択肢が悪い。修正されました。何も些細なことをするつもりはなかった。
ワールドエンジニア

19
@Mattnz:ゲームに精通している場合、彼は明らかにそれがあなたのキャラクター致命的である可能性があることを意味ます。これは完全に真実の声明です。
メイソンウィーラー

8
回答者がダイヤモンドを持っているため、答えが正しい必要があるため、+ 1。
psr

8
リアルタイムガベージコレクターは古くから存在しています。
ヨルグWミットタグ

30

実際のレンガはメモリ割り当てでした-最悪の場合、JavaはCの52倍、C ++の25倍のメモリを割り当てました。

質問の基礎となる数字を理解していますか?

  • どのくらいのメモリが割り当てられましたか?
  • プログラムは何をしていましたか?

これらのJavaプログラムとCプログラムの間に大きな相違がある場合、それはほとんどの場合、libcが必要とするものに対するデフォルトのJVMメモリ割り当てです

  • n-body
    Javaプログラム13,996KB :: Cプログラム320KB :: Free Pascal 8KB

メモリの割り当てが必要なタスクを調べます(または、追加のバッファーを使用してマルチコアプログラムからの結果を蓄積します)。

  • マンデルブロ
    Javaプログラム67、880キロバイト:: Cプログラム30、444キロバイト

  • K-ヌクレオチド
    Javaプログラム494、040キロバイト:: Cプログラム153、452キロバイト

  • 逆補完する
    Javaプログラム511、484キロバイト:: Cプログラム248、632キロバイトを

  • 正規表現-DNA
    のJavaプログラム557、080キロバイト:: Cプログラム289、088キロバイト

  • バイナリツリー
    Javaプログラム506、592キロバイト:: Cプログラム99、448キロバイト

...今日、汎用言語を選択する際のメモリ使用量は問題になりますか?

解決する必要がある特定の問題を解決するための特定のアプローチの特定の使用が、使用される特定のプラットフォームで利用可能なメモリの特定の制限によって制約されるかどうかによって異なります。


3
数字を掘り下げることについてのあなたの主張は有効であり、そのサイトには確かに彼らのテストに関する免責事項がかなりあります。あなたの答えは、コアの質問に直接対処することで強化されます。これは、「メモリ使用量を気にする必要がありますか?」です。

1
比較的貧弱な質問を回収した優れた回答(曖昧に指定されたベンチマークは、時期尚早な最適化よりもさらに悪い:)。分析をサポートするデータは、適切に提示され、具体的であり、思考のための素晴らしい食物となります。確かに価値が「模範的な答えは」恵み
グナット

17

すべてのものと同様に、それはトレードオフです。

単一のユーザーデスクトップで実行するアプリケーションを構築し、そのマシンのRAMの大部分を制御することが合理的に期待できる場合、実装速度のためにメモリ使用量を犠牲にする価値があります。同じマシンをターゲットにしているが、同時に実行されている他の多くのメモリを消費するアプリケーションと競合する小さなユーティリティを構築している場合、そのトレードオフについてより慎重にしたい場合があります。ユーザーは、実行中にすべてのメモリを必要とするゲームで問題ない場合があります(ただし、ワールドエンジニアが指摘しているように、ガベージコレクターが定期的にアクションを一時停止してスイープを行うことを決定した場合)-バックグラウンドで実行している音楽プレーヤーが他のことを行っているときに、大量のメモリを消費し、働く能力を妨げます。Webベースのアプリケーションを構築している場合、サーバーで使用するメモリによってスケールアウトする能力が制限され、同じユーザーセットをサポートするためにより多くのアプリケーションサーバーにより多くのお金を費やす必要があります。それは会社の経済に大きな影響を与える可能性があるため、そのトレードオフについては非常に慎重になりたいかもしれません。サーバーで使用するメモリにより、スケールアウトする能力が制限され、同じユーザーのセットをサポートするためにより多くのアプリケーションサーバーにより多くのお金を費やす必要があります。それは会社の経済に大きな影響を与える可能性があるため、そのトレードオフについては非常に慎重になりたいかもしれません。サーバーで使用するメモリにより、スケールアウトする能力が制限され、同じユーザーのセットをサポートするためにより多くのアプリケーションサーバーにより多くのお金を費やす必要があります。それは会社の経済に大きな影響を与える可能性があるため、そのトレードオフについては非常に慎重になりたいかもしれません。


8

それは多くの要因、特にあなたが働いている規模に依存します。

議論のためだけに、メモリが30倍、CPU使用率が2倍と仮定します。

Cで記述された場合、10メガバイトのメモリと1ミリ秒のCPUを必要とする対話型プログラムを扱っている場合、それはほとんど重要ではありません。また、携帯電話やタブレットでも意味がありそうにありません。

ただし、1台のサーバーの約半分のリソースが必要な場合と15台のサーバーが必要な場合との違いは、はるかに大きなステップです。特に、15台のサーバーへのスケールアウトには、開発に少なからず多くの追加作業が必要になる可能性が高いためです。将来の拡張に関しては、顧客ベースが大幅に成長しない限り、あなたが言及するのと同じ要因は、それが現在1つのサーバーで実行される場合、そのサーバーを超えると、あなたは問題なく1台の新しいサーバーに置き換えることができます。

あなたが本当に考慮しなければならない他の要因は、特定のタスクで見られる開発コストの正確な差です。今、あなたは基本的に方程式の片側を見ている。費用対便益の良いアイデアを得るには、(明らかに)費用と便益の両方を検討する必要があります。本当の質問は基本的に「xはyよりも大きいのか?」です。-しかし、xだけを見ても判断できません。明らかにyも見る必要があります。


2
スケールに注意する場合は+1。この記事参照して、大規模なリソース管理を実際に評価してください
ガイCoderの

6

メモリ管理は、今日の世界では絶対に関連しています。ただし、期待する方法ではありません。ガベージコレクションされた言語でも、参照リークがないことを確認する必要があります

これがあなたのコードである場合、あなたは何か間違ったことをしています:

static List<string> Cache;

...
Cache.Add(foo); //and then never remove anything from Cache

ガベージコレクションは、再度使用できないように作成しない限り、何らかの参照を二度と使用しないことを魔法のように知ることはできません。つまり、を実行することCache=nullで、ガベージコレクターに効果的に警告します。もうアクセスしてください。

それよりも複雑ですが、リファレンスリークは、従来のメモリリークと同じくらい、あるいはそれ以上に有害です。

ガベージコレクターが収まらない場所もいくつかあります。たとえば、ATTiny84は512バイトのコードROMと32バイトのRAMを備えたマイクロコントローラです。がんばろう!それは極端であり、おそらくアセンブリ以外ではプログラミングされないでしょうが、それでもです。他のケースでは、1Mのメモリがあるかもしれません。確かに、ガベージコレクターを取り付けることはできますが、プロセッサが非常に遅い場合(制限により、またはバッテリーを保持するために)、プログラマー知っていることを追跡するのが高すぎるため、ガベージコレクターを使用する必要はありません。。

また、保証された応答時間を必要とする場合、ガベージコレクションを使用することが著しく難しくなります。たとえば、ハートモニターなどがあり、1あるポートでを受信した場合、10ミリ秒以内に適切な信号または何かで応答できることを保証する必要があります。応答ルーチンの途中で、ガベージコレクターがパスを作成する必要があり、応答に100ミリ秒かかる場合は、誰かが死んでいる可能性があります。タイミング要件を保証する必要がある場合、ガベージコレクションは不可能ではないにしても非常に困難です。

もちろん、最新のハードウェアでも、ガベージコレクターのオーバーヘッドを気にせずにパフォーマンスを2%余分に必要とする場合があります。


3

ドナルド・クヌースが言ったように、時期尚早の最適化はすべての悪の根源です。メモリがボトルネックになると信じる理由がない限り、心配する必要はありません。そして、ムーアの法則がまだメモリ容量の増加をもたらしていることを考えると(より高速なシングルスレッドコードを取得していない場合でも)、将来的にはメモリよりもさらに制約が少なくなると信じるあらゆる理由があります今日です。

とは言っても、最適化が時期尚早でなければ、必ずそれを行います。私は現在、メモリ使用量を詳細に理解しているプロジェクトに個人的に取り組んでおり、実際には正確な制御が必要であり、ガベージスイープは私を殺します。したがって、私はこのプロジェクトをC ++で行っています。しかし、その選択は私にとっては数年に一度のイベントのようです。(願わくば、数週間のうちにC ++に再び触れないようになります。)


4
この態度は、ページングを続ける信じられないほど遅いコンピューター上で肥大化したエンタープライズソフトウェアになってしまう方法です。誰もが「私のアプリはより多くのメモリを必要としますが、気にする人は、それは実質的に無料です!」と言います。そして、4GB RAMマシンの実行速度が10年前の512MB RAMマシンよりも遅くなる、メモリを大量に消費するアプリの完全なスタックになります。
MrFox

@MrFox実際、エンタープライズソフトウェアの問題は、エンタープライズソフトウェアを使用することに決めた人が、それに苦しむ人ではないということです。壊れている理由の優れた説明については、lists.canonical.org / pipermail / kragen-tol / 2005-April / 000772.htmlを参照してください。残りについては、メモリ使用量を心配することが時々必要であるという私の指摘を逃しましたか?
btilly

3

「ビッグデータ」を扱う人々にとって、メモリ管理は依然として大きな問題です。天文学、物理学、バイオインフォマティクス、機械学習などのプログラムはすべて、数ギガバイトのデータセットを処理する必要があり、関連する部分をメモリに保持できる場合、プログラムは非常に高速に実行されます。RAMが128GBのマシンで実行しても、問題は解決しません。

GPUを利用するという問題もありますが、おそらくそれを組み込みシステムとして分類するでしょう。CUDAまたはOpenCLを使用する際のハード思考のほとんどは、データをメインメモリからGPUメモリに転送する際のメモリ管理の問題に帰着します。


1

公平を期すために、世の中のJavaの多くは、パフォーマンスを殺し、メモリを浪費する、真に意味のないクラス爆発的なパターンを楽しんでいますが、そのメモリのどれだけが、理論上(まあ)実行できるJVMなのでしょうか新しいアプリを完全に書き換える必要なく、複数の環境で同じアプリを使用できます。したがって、設計上のトレードオフの問題は、「ユーザーのメモリのどれだけが、開発の利点として価値があるのか​​」ということになります。

これは、IMOを検討するのに完全に価値があり、合理的なトレードオフです。しかし、私を怒らせているのは、現代のPCは非常に強力でメモリが非常に安いため、そのような懸念や肥大化した機能や肥大化したコードを完全に無視し、多くのもののように見える選択を怠ることができるという概念です私は今、Windows PCでやっていますが、Window '95と同じくらいの時間がかかります。まじで、Word?ユーザーベースの80%が実際に必要とする新しいがらくたは、18年でどれほど追加できるでしょうか。スペルチェックのプリウィンドウが正しいことは確かですか?しかし、私たちは記憶について話していましたが、あなたがそれをたくさん持っている場合は必ずしもスピードではありませんので、私は脱線します。

ただし、もちろん、わずか数KBのバージョンを取得するのに2年ではなく、おそらく数メガバイトのコストで2週間でアプリを完成させることができるなら、数メガグラムが(私は、平均的なユーザーのマシンで4〜12のギグを行ってから、だらしのないアイデアをsc笑します。

しかし、これはトレードオフの問題を超えてScalaと関係がありますか?ガベージコレクションだからといって、スコープやクロージャに含まれるものや、そのままにしておくべきか、それが使用されるような方法で使用すべきかについて、データの流れについて常に考えているとは限らないという意味ではありません不要になったGCによって割り当て解除されます。それは私たちJavaScript UIのWeb開発者でさえ考えなければならないことであり、perfに精通したがんのような他の問題領域(FlashやAppletなどでチャンスがあれば殺したはずです)私たちがいること。


0

プログラミングにおけるメモリ管理は無関係な関心事になっていますか?

メモリ管理(または制御)は、実際にCとC ++を使用している主な理由です。

現在、メモリは比較的安価です。

高速メモリではありません。i7上のL1の32KBデータキャッシュ、L2の256KB、L3 /コアの2MBなど、まだ少数のレジスタを探しています。それは言った:

作業メモリに厳しい制限があるターゲットプラットフォーム(つまり、組み込みシステムなど)で話さない場合、今日汎用言語を選択する際にメモリ使用量を考慮する必要がありますか?

一般的なレベルでのメモリ使用量は、おそらくそうではありません。私は、たとえば50メガバイトのDRAMと数百メガバイトのハードディスクスペースを必要とするメモ帳のアイデアが好きではないという点で、少し非実用的です。私は長い間あちこちにいて、このような単純なアプリケーションがキロバイトで実行できることに対して比較的多くのメモリを必要とするのを見るのは奇妙で気分が悪いだけです。そうは言っても、もしそれが素晴らしく、反応が良ければ、そのようなことに出会った場合、私は自分自身と一緒に暮らすことができるかもしれません。

私の分野でメモリ管理が私にとって重要である理由は、一般的にメモリ使用量をそれほど減らすことではありません。数百メガバイトのメモリ使用は、そのメモリのどれにも頻繁にアクセスされない場合、必ずしも重要でない方法でアプリケーションの速度を落とすわけではありません(例:ボタンクリックまたは他の形式のユーザー入力時のみ、これは非常にまれですボタンを1秒間に100万回クリックする可能性のある韓国のStarcraftプレイヤーについて話しています)。

私の分野で重要な理由は、それらのクリティカルパスで非常に頻繁にアクセスされる(例:単一のフレームごとにループされる)メモリを密に近づけることです。毎フレームループですべてにアクセスする必要がある100万個の要素のうち1つだけにアクセスするたびにキャッシュミスが発生することは望ましくありません。64バイトのキャッシュラインなど、大きなメモリを低速のメモリから高速のメモリに階層を移動するときに、それらの64バイトにすべて関連データが含まれている場合、複数の要素に相当するデータをそれらの64バイトに収めることができれば、非常に役立ちます。データが追い出される前にすべてを使用するようなアクセスパターンがある場合。

ギガバイトがあっても、100万個の要素について頻繁にアクセスされるデータは20メガバイトにしかならない可能性があります。キャッシュミスを最小限に抑えるためにメモリが密集して密集している場合、描画されるフレームごとにフレームレートがループするため、フレームレートに大きな違いが生じます。これが、メモリ管理/制御が非常に役立つ場合です。数百万の頂点を持つ球の単純な視覚的な例:

ここに画像の説明を入力してください

メッシュの永続的なデータ構造表現をテストしているため、上記は実際に可変バージョンよりも遅くなりますが、それを除けば、その半分のデータでさえそのようなフレームレートを達成するのに苦労していました(確かに私の苦労以来ハードウェアは速くなっています) )メッシュデータのキャッシュミスとメモリ使用を最小限に抑えることができなかったためです。メッシュは、ポリゴン、エッジ、頂点、ユーザーがアタッチしたいテクスチャマップ、ボーンウェイトなど、同期を維持する必要がある相互依存データを非常に多く格納するため、この点で扱いにくい最も複雑なデータ構造の一部です。カラーマップ、選択セット、モーフターゲット、エッジウェイト、ポリゴンマテリアルなど。

私は過去数十年間に多くのメッシュシステムを設計および実装してきましたが、その速度は多くの場合メモリ使用量に非常に比例していました。作業を始めたときよりもはるかに多くのメモリを使用しているにもかかわらず、新しいメッシュシステムは最初の設計(ほぼ20年前)の10倍以上高速であり、想い出。最新バージョンでは、インデックス圧縮を使用してできるだけ多くのデータを圧縮します。また、解凍の処理オーバーヘッドにもかかわらず、貴重な高速メモリがほとんどないため、圧縮により実際にパフォーマンスが向上しました。テクスチャ座標、エッジの折り目、マテリアルの割り当てなどを含む100万ポリゴンメッシュに、約30メガバイトの空間インデックスを合わせることができるようになりました。

これは、800万個を超える四角形と、GF 8400(これは数年前のもの)を搭載したi3でのマルチ解像度サブディビジョンスキームを備えた可変プロトタイプです。不変バージョンよりも高速ですが、本番環境では使用しません。不変バージョンの方が保守がずっと簡単で、パフォーマンスへの影響もそれほど悪くないからです。ワイヤフレームはファセットを示すのではなく、パッチ(ワイヤは実際には曲線で、そうでない場合はメッシュ全体が黒一色になります)を示しますが、ファセット内のすべてのポイントはブラシによって変更されます。

ここに画像の説明を入力してください

とにかく、上記のいくつかを具体的な例と、メモリ管理が非常に役立つ領域を示したいと思っていました。メモリが豊富で安価であると人々が言うとき、私は少しイライラする傾向があります。それは、DRAMやハードドライブのような遅いメモリについて話しているからです。私たちが高速メモリについて話しているとき、それはまだとても小さくてとても貴重であり、本当に重要な(つまり、すべてではなく一般的なケース)パスのパフォーマンスは、その少量の高速メモリを再生し、できるだけ効果的にそれを利用することに関連します。

この種のことのために、たとえばC ++などの高レベルのオブジェクトを設計できる言語を使用しながら、これらのオブジェクトを1つまたは複数の連続した配列に格納でき、そのようなすべてのオブジェクトは、オブジェクトごとに不要なメモリオーバーヘッドなしで連続して表されます(例:すべてのオブジェクトがリフレクションまたは仮想ディスパッチを必要とするわけではありません)。これらのパフォーマンスが重要な領域に実際に移動すると、オブジェクトのオーバーヘッド、GCコストを回避し、頻繁にアクセスされるメモリを維持するために、オブジェクトプールをいじったり、プリミティブデータ型を使用したりするなど、メモリを制御することが生産性の向上になります一緒に隣接。

したがって、メモリ管理/制御(またはその欠如)は、実際には、どの言語が最も生産的に問題に取り組むことができるかを選択するための私の場合の支配的な理由です。私は間違いなく、パフォーマンスに重要ではないコードを共有します。そのために、Cから簡単に埋め込むことができるLuaを使用する傾向があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.