1 | #include <iostream> |
---|---|
2 | #include <iomanip> |
3 | |
4 | #if __SSE2__ |
5 | #include <emmintrin.h> |
6 | #endif |
7 | |
8 | #include <common/Types.h> |
9 | #include <IO/ReadHelpers.h> |
10 | #include <IO/ReadBufferFromFileDescriptor.h> |
11 | |
12 | /** Counts number of 0 in a file. |
13 | * Outputs "fullness" of file - ration of non-0 bytes to the expected number of non-0 bytes in file with random bytes. |
14 | */ |
15 | |
16 | int main(int argc, char ** argv) |
17 | { |
18 | #if __SSE2__ |
19 | try |
20 | { |
21 | DB::ReadBufferFromFileDescriptor in(STDIN_FILENO); |
22 | size_t zeros = 0; |
23 | UInt64 limit = 0; |
24 | |
25 | if (argc == 2) |
26 | limit = DB::parse<UInt64>(argv[1]); |
27 | |
28 | while (!in.eof()) |
29 | { |
30 | const __m128i zero = {0}; |
31 | for (; in.position() + 15 < in.buffer().end(); in.position() += 16) |
32 | { |
33 | __m128i bytes = *reinterpret_cast<const __m128i *>(in.position()); |
34 | __m128i byte_mask = _mm_cmpeq_epi8(bytes, zero); |
35 | UInt16 bit_mask = _mm_movemask_epi8(byte_mask); |
36 | zeros += __builtin_popcount(bit_mask); |
37 | } |
38 | |
39 | for (; in.position() < in.buffer().end(); ++in.position()) |
40 | if (*in.position() == 0) |
41 | ++zeros; |
42 | |
43 | if (limit && in.count() >= limit) |
44 | break; |
45 | } |
46 | |
47 | std::cout << std::fixed |
48 | << 1 - std::max(0.0, static_cast<double>(zeros) / in.count() - 1.0 / 256) |
49 | << std::endl; |
50 | } |
51 | catch (const DB::Exception & e) |
52 | { |
53 | std::cerr << e.what() << ", "<< e.message() << std::endl |
54 | << std::endl |
55 | << "Stack trace:"<< std::endl |
56 | << e.getStackTrace().toString() |
57 | << std::endl; |
58 | throw; |
59 | } |
60 | #else |
61 | std::cerr << "Only for x86_64 arch "<< std::endl; |
62 | #endif |
63 | |
64 | return 0; |
65 | } |
66 |