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
16int 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