私は多くのデータを集めたPerlスクリプトを持っています。小さく始まるが、ドット(concatentation)演算子の繰り返し使用のために本当に長くなる文字列変数の束があります。この方法で文字列を拡張すると、繰り返し割り当てが行われますか?はいの場合は、文字列を事前に割り当てる方法はありますか?Perlで文字列をどのように事前に割り当てることができますか?
答えて
はい、拡張していることがわかっている拡張文字列は良い考えです。
「x」演算子を使用してこれを行うことができます。例えば、1000のスペース事前に割り当てる:
$ sでの= "" X 1000:
Perlの文字列は変更可能ですが、その文字列に追加するとは、文字列の重複ペナルティが発生しませありません。
あなたは「速い」方法を見つけたいすべてを試すことができますが、これは時期尚早の最適化の本当に臭いです。例えば
、私はハードワークを抽象化するクラスを手早く。それは完璧に動作しますが、それはすべての馬鹿馬鹿しいトリックのために、本当に遅いです。ここで
が結果だ:
Rate magic normal
magic 1.72/s -- -93%
normal 23.9/s 1289% --
はい、そうです、Perlは私が立派な実装だと思ったものよりも1200パーセント高速です。
でも知られている問題ではありませんものを最適化しようとしないで、あなたのコードをプロファイリングし、実際の問題が何であるかを見つけます。
#!/usr/bin/perl
use strict;
use warnings;
{
package MagicString;
use Moose;
has _buffer => (
isa => 'Str',
is => 'rw',
);
has _buffer_size => (
isa => 'Int',
is => 'rw',
default => 0,
);
has step_size => (
isa => 'Int',
is => 'rw',
default => 32768,
);
has _tail_pos => (
isa => 'Int',
is => 'rw',
default => 0,
);
sub BUILD {
my $self = shift;
$self->_buffer(chr(0) x $self->step_size);
}
sub value {
my $self = shift;
return substr($self->{buffer}, 0, $self->{_tail_pos});
}
sub append {
my $self = shift;
my $value = shift;
my $L = length($value);
if (($self->{_tail_pos} + $L) > $self->{_buffer_size }){
$self->{buffer} .= (chr(0) x $self->{step_size});
$self->{_buffer_size} += $self->{step_size};
}
substr($self->{buffer}, $self->{_tail_pos}, $L, $value);
$self->{_tail_pos} += $L;
}
__PACKAGE__->meta->make_immutable;
}
use Benchmark qw(:all :hireswallclock);
cmpthese(-10 , {
magic => sub{
my $x = MagicString->new();
for (1 .. 200001){
$x->append("hello");
}
my $y = $x->value();
},
normal =>sub{
my $x = '';
for (1 .. 200001){
$x .= 'hello';
}
my $y = $x;
}
});
#use Data::Dumper;
#print Dumper(length($x->value()));
Perlは文字列を複製しないと言うと真偽の半分に過ぎません。 Perlは文字列に余分な文字を割り当てるだけなので、Perlは追加時に文字列を含むメモリを増やす可能性が非常に高いでしょう。これにより、メモリがコピーされる可能性があります。しかし、これはあなたのシステムのメモリマネージャで非常に高速です。 O(n)は数学のクラスでO(logn)を打つことを覚えていますが、現実世界ではアルゴリズムの一定時間が重要です。 Cは速いです。 – Schwern
実際、O(1)が1ステップで数日間であればO(1)はあまり良くありませんが、O(n^2)では数秒しかかかりません:) データサイズが非常に大きいO(n^2)アプローチが数週間を超え、そのサイズのデータセットが一般的であることを示しています。 –
はい、Perlは文字列を増やすと繰り返し再割り当てされます。 Perlは文字列に余分なスペースを割り当てますが、数バイトしか割り当てません。これはDevel :: Peekを使って見ることができます。この再割り当ては非常に高速であり、しばしば実際にメモリをコピーしません。あなたのメモリマネージャーを信頼してください。それがC言語ではなくPerlでプログラミングしている理由です。まずはベンチマークしてください!
$#array = $num_entries
で配列を事前に割り当て、keys %hash = $num_keys
でハッシュを割り当てることはできますが、length $string = $strlen
ではハッシュが機能しません。ここにはclever trick I dug up on Perlmonksがあります。
my $str = "";
vec($str, $length, 8)=0;
$str = "";
また、XSに入る場合は、SvGROW()
に電話することができます。配列を使用して、それをすべて一緒に参加する
混沌の提案は倍以上のメモリを使用します。配列のメモリ。配列内の各要素に割り当てられた各スカラーのメモリー。各スカラー要素に保持されている文字列のメモリ。参加時のコピーのメモリ。コードが単純になる場合は実行してください。ただし、メモリを節約しているとは思わないでください。
私は、配列に/道に参加行くだろう。いくつかの後の時点でのデバッグのためのすべての要素へのアクセス権を持っている、
push(@array, $crunched_bit)
そして$str = join('', @array)
、より多くの何もない場合。
これは、すべての配列要素が新しいSVを必要とするので、非常に余分なメモリを使い果たします。 –
具体的なPerl文字列の実装方法はわかりませんが、それはconstant amortized timeです。つまり、たとえ文字列を事前に割り当てる方法を見つけたとしても、すべてのスクリプトのユーザーのために保存する時間は、スタックオーバーフローでthis questionを要求した時間よりも短くなります。
- 1. カーネルモジュールを書くとき、どのように文字ポインタに文字列値を割り当てますか?
- 2. Pythonの1つの文で文字列を分割して割り当てることはできますか?
- 3. Jquery:どのように再帰的に文書のボタンを割り当てることができますか?
- 4. $に割り当てることは正直ですか? Perlで?
- 5. オブジェクトのセル配列を事前に割り当てます
- 6. この文字列をどのように部分文字列にすることができますか?
- 7. 文字列型に[String]型の値を割り当てることができませんか?テキストラベル付き
- 8. 配列から文字列をintに割り当てることができません
- 9. "名前付き定数に割り当てることができません"(変数の再割り当て)
- 10. 浮動小数点型のポインターに文字列を割り当てることができますか?
- 11. C#でのArrayListに文字列を割り当てると、
- 12. EclipseLinkとシーケンスジェネレータの事前割り当て
- 13. このコンテキストで「空の文字列を割り当てる」とはどういう意味ですか?
- 14. RStudioでスクリプトを書くときにギリシャ文字にどのように値を割り当てることができますか?
- 15. どのようにしてmoodleのユーザに "coursecreator"ロールを割り当てることができますか?
- 16. どのようにしてクラスメソッドをHashMap内の値に割り当てることができますか?
- 17. $ this-> Html-> link(..);でIDとクラスをどのように割り当てることができますか?
- 18. 文字列配列に引数を割り当てるにはどうすればよいですか?
- 19. 列の一意の文字列に番号を割り当てるにはどうすればよいですか?私が意味する。これにより
- 20. どのようにLinuxのプロセスにCPUリソースを動的に割り当てることができますか?
- 21. どのようにしてゲストをゲストに割り当てることができますか?
- 22. どのようにクラスをNSStringオブジェクトからobjective-cで割り当てることができますか?
- 23. C++での文字列割り当て
- 24. リストの理解の中でどのように割り当てを行うことができますか?
- 25. どのように私はこのテキストhorizzontalを割り当てることができますか?
- 26. railsでself.attribute =を使わないでどのように割り当てることができますか?
- 27. PHP:MySQL Queryから変数にどのように値を割り当てることができますか?
- 28. 文字列の割り当てにエラーがあります。 (C++)
- 29. チタンの文字列をどのように分割(分割)できますか?
- 30. スタティッククラス内のスタティックオブジェクトのプロパティにどのように値を割り当てることができますか?
配列内のすべての要素はすべてのオーバーヘッドを持つSVを作成しますが、あなたはこのように多くのメモリを使い果たします。 –