আমি কোনও ফাইল (বাইনারি বা পাঠ্য) অনুলিপি করার জন্য একটি ভাল উপায় অনুসন্ধান করি। আমি বেশ কয়েকটি নমুনা লিখেছি, সবাই কাজ করে। তবে আমি পাকা প্রোগ্রামারদের মতামত শুনতে চাই।
আমি ভাল উদাহরণগুলি হারিয়েছি এবং এমন একটি উপায় অনুসন্ধান করেছি যা সি ++ এর সাথে কাজ করে।
ANSI-সি-ওয়ে
#include <iostream>
#include <cstdio> // fopen, fclose, fread, fwrite, BUFSIZ
#include <ctime>
using namespace std;
int main() {
clock_t start, end;
start = clock();
// BUFSIZE default is 8192 bytes
// BUFSIZE of 1 means one chareter at time
// good values should fit to blocksize, like 1024 or 4096
// higher values reduce number of system calls
// size_t BUFFER_SIZE = 4096;
char buf[BUFSIZ];
size_t size;
FILE* source = fopen("from.ogv", "rb");
FILE* dest = fopen("to.ogv", "wb");
// clean and more secure
// feof(FILE* stream) returns non-zero if the end of file indicator for stream is set
while (size = fread(buf, 1, BUFSIZ, source)) {
fwrite(buf, 1, size, dest);
}
fclose(source);
fclose(dest);
end = clock();
cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
cout << "CPU-TIME START " << start << "\n";
cout << "CPU-TIME END " << end << "\n";
cout << "CPU-TIME END - START " << end - start << "\n";
cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
পজিক্স-ওয়ে ( কেএন্ডআর এটি "দ্য সি প্রোগ্রামিং ল্যাঙ্গুয়েজে" আরও নিম্ন-স্তরের ব্যবহার করে)
#include <iostream>
#include <fcntl.h> // open
#include <unistd.h> // read, write, close
#include <cstdio> // BUFSIZ
#include <ctime>
using namespace std;
int main() {
clock_t start, end;
start = clock();
// BUFSIZE defaults to 8192
// BUFSIZE of 1 means one chareter at time
// good values should fit to blocksize, like 1024 or 4096
// higher values reduce number of system calls
// size_t BUFFER_SIZE = 4096;
char buf[BUFSIZ];
size_t size;
int source = open("from.ogv", O_RDONLY, 0);
int dest = open("to.ogv", O_WRONLY | O_CREAT /*| O_TRUNC/**/, 0644);
while ((size = read(source, buf, BUFSIZ)) > 0) {
write(dest, buf, size);
}
close(source);
close(dest);
end = clock();
cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
cout << "CPU-TIME START " << start << "\n";
cout << "CPU-TIME END " << end << "\n";
cout << "CPU-TIME END - START " << end - start << "\n";
cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
চুম্বন-সি ++ - Streambuffer একমুখী
#include <iostream>
#include <fstream>
#include <ctime>
using namespace std;
int main() {
clock_t start, end;
start = clock();
ifstream source("from.ogv", ios::binary);
ofstream dest("to.ogv", ios::binary);
dest << source.rdbuf();
source.close();
dest.close();
end = clock();
cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
cout << "CPU-TIME START " << start << "\n";
cout << "CPU-TIME END " << end << "\n";
cout << "CPU-TIME END - START " << end - start << "\n";
cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
কপি-অ্যালগরিদম-সি ++ - পথ
#include <iostream>
#include <fstream>
#include <ctime>
#include <algorithm>
#include <iterator>
using namespace std;
int main() {
clock_t start, end;
start = clock();
ifstream source("from.ogv", ios::binary);
ofstream dest("to.ogv", ios::binary);
istreambuf_iterator<char> begin_source(source);
istreambuf_iterator<char> end_source;
ostreambuf_iterator<char> begin_dest(dest);
copy(begin_source, end_source, begin_dest);
source.close();
dest.close();
end = clock();
cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
cout << "CPU-TIME START " << start << "\n";
cout << "CPU-TIME END " << end << "\n";
cout << "CPU-TIME END - START " << end - start << "\n";
cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
নিজস্ব-বাফার-সি ++ - পথ
#include <iostream>
#include <fstream>
#include <ctime>
using namespace std;
int main() {
clock_t start, end;
start = clock();
ifstream source("from.ogv", ios::binary);
ofstream dest("to.ogv", ios::binary);
// file size
source.seekg(0, ios::end);
ifstream::pos_type size = source.tellg();
source.seekg(0);
// allocate memory for buffer
char* buffer = new char[size];
// copy file
source.read(buffer, size);
dest.write(buffer, size);
// clean up
delete[] buffer;
source.close();
dest.close();
end = clock();
cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
cout << "CPU-TIME START " << start << "\n";
cout << "CPU-TIME END " << end << "\n";
cout << "CPU-TIME END - START " << end - start << "\n";
cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
লিনাক্স-ওয়ে // এর কার্নেল> = 2.6.33 প্রয়োজন
#include <iostream>
#include <sys/sendfile.h> // sendfile
#include <fcntl.h> // open
#include <unistd.h> // close
#include <sys/stat.h> // fstat
#include <sys/types.h> // fstat
#include <ctime>
using namespace std;
int main() {
clock_t start, end;
start = clock();
int source = open("from.ogv", O_RDONLY, 0);
int dest = open("to.ogv", O_WRONLY | O_CREAT /*| O_TRUNC/**/, 0644);
// struct required, rationale: function stat() exists also
struct stat stat_source;
fstat(source, &stat_source);
sendfile(dest, source, 0, stat_source.st_size);
close(source);
close(dest);
end = clock();
cout << "CLOCKS_PER_SEC " << CLOCKS_PER_SEC << "\n";
cout << "CPU-TIME START " << start << "\n";
cout << "CPU-TIME END " << end << "\n";
cout << "CPU-TIME END - START " << end - start << "\n";
cout << "TIME(SEC) " << static_cast<double>(end - start) / CLOCKS_PER_SEC << "\n";
return 0;
}
পরিবেশ
- জিএনইউ / লিনাক্স (আর্চলিনাক্স)
- কার্নেল ৩.৩
- জিলিবিসি -২.১৫, এলআইবিএসটিডিসি ++ ৪.7 (জিসিসি-এলআইবিএস), জিসিসি ৪.7, কোরিউটিলস ৮.১6
- রুনলেভেল 3 (মাল্টিউজার, নেটওয়ার্ক, টার্মিনাল, কোনও জিইউআই নেই) ব্যবহার করা হচ্ছে
- ইনটেল এসএসডি-পোস্টভিলি 80 জিবি, 50% পর্যন্ত পূর্ণ
- একটি 270 এমবি ওজিজি-ভিডিও-ফাইল অনুলিপি করুন
ধাপ পুনর্গঠন কর
1. $ rm from.ogg
2. $ reboot # kernel and filesystem buffers are in regular
3. $ (time ./program) &>> report.txt # executes program, redirects output of program and append to file
4. $ sha256sum *.ogv # checksum
5. $ rm to.ogg # remove copy, but no sync, kernel and fileystem buffers are used
6. $ (time ./program) &>> report.txt # executes program, redirects output of program and append to file
ফলাফল (সিপিইউ সময় ব্যবহার করা হয়েছে)
Program Description UNBUFFERED|BUFFERED
ANSI C (fread/frwite) 490,000|260,000
POSIX (K&R, read/write) 450,000|230,000
FSTREAM (KISS, Streambuffer) 500,000|270,000
FSTREAM (Algorithm, copy) 500,000|270,000
FSTREAM (OWN-BUFFER) 500,000|340,000
SENDFILE (native LINUX, sendfile) 410,000|200,000
ফাইলসাইজ পরিবর্তন হয় না।
sha256sum একই ফলাফল মুদ্রণ।
ভিডিও ফাইলটি এখনও প্লেযোগ্য।
প্রশ্নাবলি
- আপনি কোন পদ্ধতি পছন্দ করবেন?
- আপনি কি আরও ভাল সমাধান জানেন?
- আপনি আমার কোড কোন ভুল দেখতে পাচ্ছেন?
আপনি কি সমাধান এড়ানোর কোনও কারণ জানেন?
FSTREAM (KISS, Streambuffer)
আমি সত্যিই এটি পছন্দ করি কারণ এটি সত্যিই সংক্ষিপ্ত এবং সহজ। যতদূর আমি জানি অপারেটর << rdbuf () এর জন্য অতিরিক্ত লোড হয়েছে এবং কোনও কিছুই রূপান্তর করে না। সঠিক?
ধন্যবাদ
আপডেট 1
আমি সমস্ত নমুনায় উত্সটি সেভাবে পরিবর্তন করেছি, যে ফাইল বর্ণনাকারীর খোলা এবং বন্ধটি ঘড়ির পরিমাপের অন্তর্ভুক্ত () । এগুলি সোর্স কোডে অন্য কোনও উল্লেখযোগ্য পরিবর্তন নয়। ফলাফল পরিবর্তন হয়নি! আমি আমার ফলাফলগুলি ডাবল-চেক করার জন্যও সময় ব্যবহার করেছি।
আপডেট 2
এএনএসআই সি নমুনা পরিবর্তিত হয়েছে: যখন লুপের শর্তটি আর ফয়েফ () কল করে না পরিবর্তে আমি শর্তের মধ্যে ফ্রেড () সরিয়েছি । দেখে মনে হচ্ছে, কোডটি এখন 10,000 টি ঘড়ি দ্রুত চালায়।
পরিমাপ পরিবর্তিত হয়েছে: পূর্ববর্তী ফলাফলগুলি সর্বদা বাফার হত, কারণ আমি পুরানো কমান্ড লাইন আরএম টু.ওভি & অ্যান্ড সিঙ্ক এবং & সময়। / প্রোগ্রামের জন্য কয়েকবার পুনরায় পুনর্বার করেছিলাম । এখন আমি প্রতিটি প্রোগ্রামের জন্য সিস্টেমটি পুনরায় বুট করি। আনফারড ফলাফলগুলি নতুন এবং কোনও বিস্ময় প্রকাশ করে না। আনফারড ফলাফলগুলি সত্যিই পরিবর্তিত হয়নি।
যদি আমি পুরাতন অনুলিপিটি মুছে না ফেলে তবে প্রোগ্রামগুলি ভিন্নভাবে প্রতিক্রিয়া দেখায়। একটি বিদ্যমান ফাইল মুছে যাওয়ার বাফার POSIX এবং SENDFILE সঙ্গে দ্রুত, সব অন্যান্য প্রোগ্রামের ধীর হয়। হতে পারে বিকল্পগুলি কাটা বা তৈরি করা এই আচরণের উপর প্রভাব ফেলে। কিন্তু একই অনুলিপি সহ বিদ্যমান ফাইলগুলিকে ওভাররাইট করা কোনও আসল ওয়ার্ল্ড ইউজ-কেস নয়।
সিপি দিয়ে অনুলিপি সম্পাদন করতে 0.44 সেকেন্ডে আনফারড অ্যান্ড 0.30 সেকেন্ডের বাফার লাগে। সুতরাং সিপি POSIX নমুনার চেয়ে কিছুটা ধীর। আমার জন্য ভাল লাগছে।
হয়তো আমিও নমুনা এবং ফলাফল যোগ mmap () এবং copy_file()
বুস্ট :: ফাইলসিস্টেম থেকে।
আপডেট 3
আমি এটি একটি ব্লগ পৃষ্ঠায় রেখেছি এবং এটি কিছুটা প্রসারিত করেছি। স্প্লাইস () সহ যা লিনাক্স কার্নেল থেকে নিম্ন-স্তরের ফাংশন। সম্ভবত জাভা সহ আরও নমুনা অনুসরণ করবে।
http://www.ttyhoney.com/blog/?page_id=69
#include <copyfile.h> copyfile(const char *from, const char *to, copyfile_state_t state, copyfile_flags_t flags);
fstream
ফাইল অপারেশনের জন্য অবশ্যই একটি ভাল বিকল্প।