フィリップがMPAndroidChartsで行った方法でライブラリのパフォーマンスを向上させる計画はありますか?
彼の機能強化により、Android上で数千のデータポイントをスムーズにレンダリングできるようになりました。
私はios-chartsの実装をざっと見ましたが、それは最新のパフォーマンス拡張なしの元のMPAndroidCharts実装に基づいています。
何千ものポイントをレンダリングすることは、すべての商用バージョンを効果的に役に立たなくするので、ライブラリにとって非常にプラスになります(そのほとんどはとにかく時間とお金の無駄です)。
Androidバージョンの元々のパフォーマンスのボトルネックは、レンダリングコード内の(配列の)多くの追加の割り当てでした。 レンダリングコード内にメモリを割り当てないでください。 そのため、 @ PhilJayは、そのコードを事前に割り当てられたBufferに移動し、レンダリング中にレンダリング計算をBufferクラスに委任しました。
レンダリング計算をBufferクラスに移動せず、必要なメモリを同じ方法で事前に割り当てることを選択しました。ただし、レンダリング計算はレンダリングコードと同じループにあります。 このようにして、コードの管理がはるかに簡単になります。
また、レンダリング計算が追加の関数内で実行されておらず、データがレンダリングコード内で2回ではなく、1回だけループされることは、パフォーマンスの向上です。
ところで、SwiftのパフォーマンスはとにかくJavaよりもはるかに優れているので、これらの配列を事前に割り当てなくてもパフォーマンスが向上することがわかります。
それをグラフィカルに説明するために、これはレンダリングコードで行われている/行われていたことです:
また、Javaでは、抽象化(関数、クラス、継承)には大きな代償が伴うことにも注意してください。 グーグル自身が重要な勧告を書いたのは無意味ではありません:
Be careful with code abstractions
Often, developers use abstractions simply as a "good programming practice,"
because abstractions can improve code flexibility and maintenance.
However, abstractions come at a significant cost:
generally they require a fair amount more code that needs to be executed,
requiring more time and more RAM for that code to be mapped into memory.
So if your abstractions aren't supplying a significant benefit, you should avoid them.
要約すると:
ダニエルの説明をありがとう。 しかし、これから何をとるべきかはよくわかりません。
私が行ったことは、最も基本的なプロジェクトをセットアップすることであり(以下のコードを参照)、パフォーマンスはAndroidバージョンと比較できず、完全に正直でさえありません。 iPad Mini3やiPhone6などの最新のiOSデバイスでも、最大量のデータポイントの表示(完全にズームアウト)に近づくと、1,000個のデータポイントを使用すると大量のフレームドロップが発生します。 私が言ったように、MPAndroidchartsは、汗をかくことなく、はるかに遅いデバイスで数千をレンダリングできます。
func viewDidLoad()をオーバーライドする{
super.viewDidLoad()
lineChart = LineChartView(frame: view.frame);
view.addSubview(lineChart);
lineChart.backgroundColor = UIColor.whiteColor()
lineChart.descriptionText = "Just a test"
lineChart.leftAxis.enabled = false
lineChart.legend.enabled = false
setData(20)
}
func setData(range:Float) {
var count = 1000;
var xVals = Array<String>();
for(var i = 0; i<count; i++) {
xVals.append(String(i) + "");
}
var yVals = Array<ChartDataEntry>();
for (var i = 0; i<count; i++) {
var mult = range + 1
var val:Float = Float(random()) * mult + 3;
yVals.append(ChartDataEntry(value: val, xIndex: i));
}
var lineSet:LineChartDataSet = LineChartDataSet(yVals: yVals, label: " ");
lineSet.drawCirclesEnabled = false;
lineSet.drawValuesEnabled = false;
var lineData:LineChartData = LineChartData(xVals: xVals, dataSet: lineSet);
lineChart.data = lineData;
}
まだすべてのグラフのパフォーマンスをテストしていないので、すぐにテストする必要があります。
ボトルネックは、おそらくどこかで見逃した割り当てです...テストしてお知らせします! :-)
ダニエル、どうもありがとう。 あなたがこれから何を絞り出すことができるかを楽しみにしています。 iOSでMPAndroidChartsの実行可能なコンパニオンがあれば素晴らしいでしょう。
さて、私はLineChartRenderer(たとえばBarChartRendererと比較して特に遅い)で少し遊んだことがあり、InstrumentsはCGContextのdrawPathがここの原因であると言っています。
代わりにUIBezierPathを使用してこの問題を軽減しようとしましたが、パスでstroke()を呼び出すとすぐにパフォーマンスは同じになります。 その前は、描画パフォーマンスは素晴らしいですが、単純な折れ線グラフに必要なものではなく、開始点と終了点に関してパスが満たされています。
うまくいけば、これに対する解決策を見つけるためにもう少し運があります。
私は今これをテストしています、そしてはい、実際のCGContextStrokePath
はパフォーマンスの低下に苦しんでいるようです。
主要な打者の1つは破線です。 無効にすると、パフォーマンスが約2倍になります。 しかし、それはまだ千ポイントで貧弱です。
CoreGraphicsを高速化する方法を見つけるために、Appleのドキュメントを読んでいます。
はい、CoreGraphicsは間違いなくパスを遅くしています。 これは解像度が原因で発生するようです。新しいAppleデバイスの解像度は非常に高いため、レンダリングするピクセルが多くなります。
CGはGPUではなくCPUでレンダリングしていると思います。 多分誰かがそれを変える方法を知っていますか?
CGは間違いなくCPUをレンダリングに使用しており、私が知る限り、それを変更する方法はありません。
残念ながら、GPUレンダリングはOpenGLを使用することを意味します。 AndroidがCPUでこのようなものをレンダリングする方法と比較して、CGが非常に遅いのは残念です。
実際に遅いのはデバイスのCPUです。 ほとんどの場合、非常に遅い
CPUは、Androidを搭載した高速CPUよりもiOSではるかに優れたエクスペリエンスを提供します。
しかし、Appleは最適なOSがない場合については考えていませんでした
それを速く保つのに十分です。
たくさんのポイントを使うと、アニメーションを避けることができると思います-しかし
私はまだラインのパフォーマンスを改善する方法を見つけることを望んでいます
ベースのチャート。
具体的には、パス描画システムが遅いようです。
マイターとフラットネスで遊んだり、破線を無効にしたり、
アンチエイリアス-パフォーマンスは500〜700ポイントではるかに良くなります
iPhone 6、それでも1000でジャーキー
UIBezierPathを使用する可能性があります。 私が言ったように、「ストローク」を呼び出さないとすぐに、そのことは十分に高速になります。これは、基本的に、パスがストロークであり、開始点から終了点まで埋めるべきではないことをシステムに通知します。 バックグラウンドで何が起こっているのかわかりませんが、これはグラフ描画自体が問題ではないことを示しています。
ただし、折れ線グラフにUIBezierPathを適切に使用する方法が見つからなかったため、ストロークを呼び出さずにパスをだまして描画できるため、グリッド線の実行可能な候補になる可能性があります。 APIの観点からは「間違っている」とはいえ、パフォーマンスが向上するはずです。
UIBezierPathは、CGPath、CGContextDrawPath、のUIKitラッパーです。
等
場合によってはパフォーマンスの違いが見られるのは、
UIBezierPathのプロパティを使用して最初にCGを設定します。
アンチエイリアス、マイター制限など。
使い方を知っていれば、実際に使う理由は全くありません。
コアグラフィックス。
そして、はい、私たちはそのパスをストロークしたいので、「ストローク」を呼び出す必要があります...
それを埋めないでください。
ほとんどの場合、ストロークは塗りつぶしよりもシステムにとって困難です
色、線の幅に注意する必要があるため、結合
線と結合の形状の間。
10:50時金、2015年4月17日には、AlBirdie [email protected]は書きました:
UIBezierPathを使用する可能性があります。 私が言ったように、そのこと
「ストローク」を呼び出さないとすぐに十分に高速になります。
パスがストロークであり、から埋めるべきではないことをシステムに通知します
エンドポイントへの開始点。 私はそれで何が起こっているのか分かりません
背景ですが、これはグラフ描画自体がではないことを示しています
単独で発行します。ただし、UIBezierPathを適切に使用する方法が見つからなかったため
折れ線グラフ、それは1つのグリッド線の実行可能な候補になる可能性があります
ストロークを呼び出さずに描画するパスをだますことができます。 それは
APIの観点から「間違っている」とすると、パフォーマンスが向上するはずです。—
このメールに直接返信するか、GitHubで表示してください
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -93937181
。
@danielgindiアニメーションの速度が低下している場合は、アニメーションなしですべての線を描画し、それを覆うマスクビューを使用してから、マスクビューをアニメーション化してアニメーションを模倣するのはどうでしょうか。
それは素晴らしいアイデアです! :)
欠点はありますが:
それはあなたがそれでできる種類のアニメーションを不自由にするでしょう。 許す限り
チャートが「成長」するようにY軸をアニメーション化し、線が塗りつぶされる方法
X軸上もストロークだけの場合とは異なります。
試すべきことの私のリストは次のとおりです:
- どういうわけかCoreGraphicsを強化するか、レンダリングの一部を
GPU
- すべてのアニメーションフレームを事前レンダリングします-アニメーションの開始を遅らせ、
かなりの量のメモリを消費します- あなたのマスキングのアイデア-アニメーションの種類を制限します
他にアイデアがあれば聞いてみたいです!
ダニエル、GPUに作業をオフロードしてみましたか?
私は現在使用している商用ソリューション(ひどいAPI、ひどく閉じられており、アプリがクラッシュする原因となるバグがたくさんある)に本当に本当に不満を持っており、MPAndroidChartsで大きな成功を収めているので、 iOS-パフォーマンスが同等である場合、最終的にチャートを作成します。 安心してください、あなたの仕事は報われるでしょう。 ;)
いくつかの異なるテクニックを試して、数日後にアップデートを提供します!
12:38 PMで月、2015年4月20日には、AlBirdie [email protected]は書きました:
ダニエル、GPUに作業をオフロードしてみましたか?
私は現在の商用ソリューションに本当に、本当に不満を持っています
作業中(ひどいAPI、ひどく閉じられている、そして原因となるバグの負荷
アプリがクラッシュする)、そしてMPAndroidChartsでこのような大成功を収めたので、
パフォーマンスが同等であれば、最終的にiOSチャートに切り替えるのが大好きです。 残り
確かに、あなたの仕事は報われるでしょう。 ;)—
このメールに直接返信するか、GitHubで表示してください
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94408574
。
@AlBirdieどのようなパフォーマンスのボトルネックに遭遇しましたか? 私は現在、iOSチャートと同じようにチャートを描画する製品を所有しています。すでに内部にチャートライブラリがあります。 パフォーマンスについても懸念しています。現在、100〜1000個のデータセットをロードするだけですが、問題はないようです。
将来的には可能であればios-chartsに変更することも検討していますが、ライブラリにはios-chartsと競合する可能性のあるジェスチャがありました。
パフォーマンスの問題は、アニメーションのフレームレートが遅いことです。
折れ線グラフに500〜1000本の線を引きます。
ジェスチャに関して-標準のUIGestureRecognizersを使用しています-
無効化、変更、または操作できます。 すべてが標準化されています。 :-)
12:53時月、2015年4月20日には、スアン[email protected]は書きました:
@AlBirdiehttps ://github.com/AlBirdieどのようなパフォーマンス
あなたが出会ったボトルネック? 私は現在、チャートを描くだけの製品を所有しています
ios-chartsのように、私たちはすでに内部にチャートライブラリを持っていました。 私も心配します
パフォーマンスについては、現在、100〜1000個のデータセットをロードするだけですが、問題ないようです
今。将来的には、可能であればiOSチャートへの変更も検討しています。
しかし、私たちのライブラリには、ios-chartsと競合する可能性のあるジェスチャーがありました。—
このメールに直接返信するか、GitHubで表示してください
https://github.com/danielgindi/ios-charts/issues/29#issuecomment -94411060
。
@danielgindiええと、私たちはアニメーションを克服するためにマスクビューを使用していると思います...私たちの折れ線グラフにはグラデーションレイヤーがあります。 デモとして、アニメーションはX + Y方向の両方を同時に実行できますが、X方向のみを実行します。 マスクトリックがあなたを助けることができるかどうかはわかりません。
私が今頭に浮かぶのは、X + Y方向を表すベクトルがあれば、マスクトリックを使用するチャンスがあるかもしれないということです...結果を楽しみにしています!
@ liuxuan30一般的にパフォーマンスが遅いと思います。 私はアニメーションを扱っていないので、アニメーションは問題ではありません。 私は、1つのチャートに複数のデータセット(複数の株式+さまざまな指標)を含める必要がある財務チャートに取り組んでいます。 250アイテムのデータ範囲の場合、パンおよびピンチ中に一度にレンダリングする必要がある最大数千のポイントを簡単に追加できます。 私が現在使用している商用ソリューションはそれをかなりうまくやっています(OpenGLを使用すると、CPUに過負荷をかけることなく数千のポイントをレンダリングできます)が、バグ修正を数か月待たなければならないクローズドソースライブラリの友達ではありません。
特にMPAndroidChartsのAPIは非常に簡単に操作できるので、iOSチャートの方がはるかに快適だと思います。
なるほど、財務データは災害です。 サーバーは最大1000個のデータセットをモバイルデバイスに送信するように強制するため、過負荷が軽減されました。 iOSチャートにOpenGLを使用する機会はありますか? @danielgindi
OpenGLのサポートはエースになります。 今のところ、GPUでレンダリングされた折れ線グラフで十分でしょう。
残念ながら、OpenGLについてはまったくわかりません。それ以外の場合は、喜んでお手伝いさせていただきます。
パスを使用するのではなく、CGContextStrokeLineSegmentsで改善が行われるため、これを試す必要があります。
まだ物事を改善する他の方法を試しています:-)
ダニエルに感謝します。2つのバージョンを互いにベンチングして何が何であるかを確認する小さなテストアプリを作成します。 新しいLineSegmentsを使用して、どのようなパフォーマンスの向上が得られましたか?
@AlBirdie線分との違いを感じますか?
また、私はちょうど気づきました:Androidで最大のパフォーマンスを得るには、ハードウェアレイヤーに設定します-この場合、破線は破線ではなく、すべて実線です。
したがって、iOSで破線を無効にすると、最初に大幅なブーストも得られます。
しかし、実際にはCIImageでOpenGL ESを使用して描画できると思いますが、アプリが非アクティブのときに1つのGL行が実行されるとクラッシュするため、十分に注意する必要があります。
また、テクスチャを事前にレンダリングすることで、ダッシュを許可できる可能性もあります。 少し手間がかかり、私の最優先事項ではありませんが、CGContextをシームレスに置き換えることができるOpenGLレイヤーのサイドプロジェクトを開始しています。
描画のためにOpenGLに行くのではなく、CoreAnimationに下げることもできます。 たぶん、 CAShapeLayerクラスが機能する可能性があります。 複雑なパスをレンダリングする場合は、複数のCAShapeLayer
を使用することをお勧めします。そのため、線分を複数のセグメントに分割する必要がある場合があります。 Core Animationを使用すると、作業がGPUに移動します。
私の日常業務では、 @ AlBirdieが前述したように、OpenGLを多用し、アノテーション以外のすべてでCoreGraphicsをバイパスする商用製品を何年も使用してきました。 確かに、彼らはかなりスムーズなレンダリングでかなり大きなデータセットを処理できるようであり、これにはGPUを使用すると主張しています。 ただし、彼らのアプローチには大きな頭痛の種があります。特に、アプリがバックグラウンドに移行したときにOpenGLでクラッシュする非同期レンダリング呼び出し、ばかげたクラス構造、カスタマイズ性の異常な制限など、修正するのが面倒ではないように見えるバグがあります。 私が欲しいものは今日存在しませんが、iOS-Chartsではそれがそこに到達する方法かもしれないと思います。 とにかく、私にとって信頼性は毎回パフォーマンスよりも優先されますが、それはごくわずかなマージンであり、両方が非常に重要です。
私の意見では、破線は、コンピューターにカラーまたはグレースケールでレンダリングするオプションがなかった時代からの二日酔いです-純粋な白黒にレンダリングして古いように見えるものを作成しない限り、それらは必要ありません活版印刷の教科書ですね。 ;)したがって、一般的な10Kポイントの場合よりも、それらを最適化することの方がはるかに重要ではありません。
破線に関しては絶対に@onlyforartと一緒に。
あなたの商用チャートライブラリについてのあなたの説明を考えると、私たちは同じ製品を使用しているのだろうかと思います。 :)ちなみに、ようやく捨てました。 実装に3か月の大部分を要したのは(深刻なバグや制限(十字線など)を回避するのに十分な長さではなかったとしても、iOSCharts(「ばかげたクラス構造」;)ではわずか2週間でした)。 時間とお金の無駄。
@AlBirdieはい、それです。 十字線についても言及しないでください。 あまりにも多くのニューカッスルブラウンエールの助けを借りて作られ、間違いなく企業市場を対象としています(危険なAPIは、顧客を高価なサポート/メンテナンスサイクルに閉じ込めるため、実際にはプラスの販売要因です)。 あなたはそれらの人の歴史を知っていましたか? 実際(彼らの深い過去において)彼らはソフトウェア業界の真のパイオニアでした。 とにかく、今は先に進んで未来に目を向ける時です。
私たちは主にローソク足チャートを描きます(これらは金融セクターのアプリです)。 私がiOSとAndroidに本当に望んでいるのは、HTML5 / Javascriptの世界でHighCharts / HighStockを使用すると実際には非常に簡単なことです。
笑@onlyforart 、あなたはニューカッスルブラウンエールで私を持っていました。 :+1::)
私はあなたの要件(金融商品にも取り組んでいます)に関して同じ船に乗っていますが、はい、これらのチャートの実際の描画に戻りましょう。 今後のご発見をお待ちしております。
@ onlyforart 、 @ AlBirdieあなたの洞察に感謝します:-)
私たちの図書館のために営利企業の製品を捨てる人々を見るのは本当にうれしいですが、私は彼らに気分が悪いです...私は対立しています!
完全に管理されていないとクラッシュする可能性があることを知っていたので、OpenGLにこれをスライスさせることを躊躇しました。これは、UIKitアプリでは実際には不可能です。 OpenGLを使用してゲームを作成している場合、すべてがOpenGLキャンバスであり、バックグラウンドでOpenGLレンダリングを実行しようとするUIKit呼び出しについて心配する必要はありません。
@onlyforart破線についてのあなたの指摘は正しいですが、残念ながら私は破線を要求するクライアントとの経験があります。 Androidで、パフォーマンスを向上させるために、開発者がレイヤーをハードウェアレイヤーに変更し、破線が実線になることをクライアントに伝えた場合がありました。これはコストです。 もちろん、すべての描画コードをOpenGLに移動するオプションもありますが、1本の線を描画するのは頭痛の種ですが、破線のテクスチャを作成して操作することもできます。 彼らはそれに対してお金を払いたくなかったので、破線は確かにそれほど重要ではありませんでしたが、彼らはそれについて多くの騒ぎをしました。
私自身へのメモ:レンダリングにはGLKitを使用してみてください。 何が起こるか見てください。
そして私があなたのリストを取るならば:
@danielgindi 、彼らに悪い気持ちを
2番目の要件に関しては、これを実装する場合はオプションである必要があります。 チャート製品の1つにこの種の統合があり、代わりに顧客は着実に固定頻度に移行しています。 ズーム中に周波数を変更すると、平均的な財務チャートのユーザーを混乱させるだけでなく、パワーユーザーは固定周波数が必要なためにイライラすることがわかりました。
これをユーザーに強制することは想像もしていませんでした。 コードに既にフィルターが含まれていることがわかります。MPAndroidChartsでは、フィルターを設定するプロパティ(カスタムフィルターまたは組み込みフィルター)によってフィルターが有効にされていたが、構造の変更により後で削除されたことがわかります。
私たちがそれを実装するとき、機能は同じままです-それはちょうど別のクールな機能になります:-)
@AlBirdie Re "2番目の要件に関しては、これを実装する場合はオプションである必要があります。チャート製品の1つにこの種の統合があり、代わりに顧客は着実に固定頻度に移行しています。変更ズーム中の周波数は、平均的な財務チャートのユーザーを混乱させるだけでなく、パワーユーザーは固定周波数が必要だったためにイライラしました。」 完全に同意します-これは情報/非取引ユーザー向けのチャート用です。 トレーディングユーザーにはさまざまなニーズがあります。
@danielgindi Re「データソースの抽象化」時間がある場合、これは私たちが貢献できるものかもしれません。 約束はありませんが、バックログに追加します。
描画コードを別々のスレッド(CALayer.drawsAsynchronously)に分割して遊んだ人はいますか? これにより、チャートエクストラ、各データセット、グリッド、および軸を個別に描画できる場合に役立つ可能性があります。 CoreGraphicsでの非常に謙虚な経験を考えると(読んでください;まったくありません;-))、これを使った実験は行っていません。GLKitを探していたときに、それがチャートのパフォーマンスをどのように改善できるかを見つけました。
10kのデータポイントを含むローソク足チャートを表示する必要があったため、CandleStickChartRenderer.drawDataSet()で時間測定を実行しました。
ほとんどの時間はdataSet.entryIndexの呼び出しに費やされていることが判明しました(76、77行目)。
誤解されているかもしれませんが、_minX、_maxX値は常にminx、maxxがdataSet.entryIndex()から返されるため、dataSet.entryIndex()呼び出しは冗長であるように見えます
10kのデータポイントでスムーズにパン/ズームできるローソク足チャートを作成することができました。 変更することによって
CandleStickChartRenderer.swift、76,77行目:
var minx = max(dataSet.entryIndex(entry:entryFrom、isEqual:true)、0);
var maxx = min(dataSet.entryIndex(entry:entryTo、isEqual:true)+ 1、entries.count);
に
var minx = max(_minX、0);
var maxx = _maxX + 1;
LineChartRendererに同じ変更を加え、2つのデータ系列(それぞれ10kデータポイント)を組み合わせたローソク足/折れ線グラフを表示することができました。
うわー、それは@dorsoftの大幅なパフォーマンスの向上
私はこれをテストしたばかりで、自分の目を信じることができませんでした。 それぞれ250のデータポイントを持つ最大3つのデータセットを表示する4つのCombinedChartsとy軸の自動最小/最大計算を備えたiPad2でも、すべてのチャートをかなりスムーズに同時にパンおよびズームできるようになりました。 60fpsではありませんが近いです。 このような古いデバイスとWAY(!)は、前に説明した商用のOpenGLソリューションよりも高速です。
私はこれを試してみる必要があると思います:)そしてフィルとも話し合う必要があります
何か影響があるかどうかを理解してください...
私はこれを読んだばかりで、非常に興味深いように見えますが、実際にすべてのシナリオに適しているかどうかを確認するために、いくつかの徹底的なテストが必要になります:-)
ローソク足チャートのパフォーマンスを向上させたPRを作成しました。
エンハンスメントは、自動スケールの最小/最大値とゼロ値を使用して徹底的にテストされました。
ボトルネックの可能性を見つけました。 リアルタイムチャートで1秒あたりのエントリ数をチャートに追加すると、データセットのcalcMinMaxが各values.append(e)
直後に自動的に呼び出されることに気付きました。
calcMinMax関数は、.forEachを使用して最小値と最大値を決定します。これにより、CPUは60%以上、さらにメインスレッドで値のループに費やされます。
最小/最大計算を無効にするか、配列.forEachの代わりにネイティブのforループを使用して実験を行っています
@danielgindi見てください、本当に必要なすべての値のcalcMinMaxですか? コードで最小/最大Y値を手動で計算し、表示されている値のみで計算するため、ブール値を公開して最小/最大自動計算を有効/無効にし、forEach関数を削除してパフォーマンスを向上させ、関数呼び出しを回避できます。
```
open override func calcMinMax()
{
guard !values.isEmpty else { return }
_yMax = -Double.greatestFiniteMagnitude
_yMin = Double.greatestFiniteMagnitude
_xMax = -Double.greatestFiniteMagnitude
_xMin = Double.greatestFiniteMagnitude
values.forEach { calcMinMax(entry: $0) }
}
`` `
@samueleperriconeこれを別のチケットにしてください。優先します。
@jjatieありがとう、開いてください#3166
iOSの折れ線グラフに13000を超えるレコードを読み込んでいます。 ただし、グラフは読み込み中にUIをフリーズします。 また、ロード後、ユーザーが任意のポイントを選択すると、選択を強調表示するのにも時間がかかりすぎます。
最も参考になるコメント
iOSの折れ線グラフに13000を超えるレコードを読み込んでいます。 ただし、グラフは読み込み中にUIをフリーズします。 また、ロード後、ユーザーが任意のポイントを選択すると、選択を強調表示するのにも時間がかかりすぎます。