예제 #1
0
/**
 * @brief Compress a buffer with an existing @ref SquashOptions
 *
 * @param codec The name of the codec to use
 * @param[out] compressed Location to store the compressed data
 * @param[in,out] compressed_length Location storing the size of the
 *   @a compressed buffer on input, replaced with the actual size of
 *   the compressed data
 * @param uncompressed The uncompressed data
 * @param uncompressed_length Length of the uncompressed data (in bytes)
 * @param options Compression options, or *NULL* to use the defaults
 * @return A status code
 */
SquashStatus
squash_compress_with_options (const char* codec,
                              size_t* compressed_length,
                              uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)],
                              size_t uncompressed_length,
                              const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)],
                              SquashOptions* options) {
  SquashCodec* codec_real = squash_get_codec (codec);

  if (codec_real == NULL)
    return squash_error (SQUASH_NOT_FOUND);

  return squash_codec_compress_with_options (codec_real,
                                             compressed_length, compressed,
                                             uncompressed_length, uncompressed,
                                             options);
}
예제 #2
0
/**
 * @brief Compress a buffer
 *
 * @param codec The codec to use
 * @param[out] compressed Location to store the compressed data
 * @param[in,out] compressed_length Location storing the size of the
 *   @a compressed buffer on input, replaced with the actual size of
 *   the compressed data
 * @param uncompressed The uncompressed data
 * @param uncompressed_length Length of the uncompressed data (in bytes)
 * @param ... A variadic list of key/value option pairs, followed by
 *   *NULL*
 * @return A status code
 */
SquashStatus squash_codec_compress (SquashCodec* codec,
                                    size_t* compressed_length,
                                    uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)],
                                    size_t uncompressed_length,
                                    const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)],
                                    ...) {
  SquashOptions* options;
  va_list ap;

  assert (codec != NULL);

  va_start (ap, uncompressed);
  options = squash_options_newv (codec, ap);
  va_end (ap);

  return squash_codec_compress_with_options (codec,
                                             compressed_length, compressed,
                                             uncompressed_length, uncompressed,
                                             options);
}
예제 #3
0
/**
 * @brief Compress a buffer
 *
 * @param codec The name of the codec to use
 * @param[out] compressed Location to store the compressed data
 * @param[in,out] compressed_length Location storing the size of the
 *   @a compressed buffer on input, replaced with the actual size of
 *   the compressed data
 * @param uncompressed The uncompressed data
 * @param uncompressed_length Length of the uncompressed data (in bytes)
 * @param ... A variadic list of key/value option pairs, followed by
 *   *NULL*
 * @return A status code
 */
SquashStatus
squash_compress (const char* codec,
                 size_t* compressed_length,
                 uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)],
                 size_t uncompressed_length,
                 const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)],
                 ...) {
  SquashOptions* options;
  va_list ap;
  SquashCodec* codec_real = squash_get_codec (codec);

  if (codec_real == NULL)
    return squash_error (SQUASH_NOT_FOUND);

  va_start (ap, uncompressed);
  options = squash_options_newv (codec_real, ap);
  va_end (ap);

  return squash_codec_compress_with_options (codec_real,
                                             compressed_length, compressed,
                                             uncompressed_length, uncompressed,
                                             options);
}
예제 #4
0
int main(int argc, char *argv[])
{
  int ret;
  off_t size = 0, size_c = 0;
  size_t len, len_c;
  FILE *in;
  void *in_buf, *out_buf;
  uint64_t full_len, out_len;
  struct stat st;
  void *in_map = NULL;
  void *out_map = NULL;
  int out_fd;
  double time = 0.0;
#ifdef USE_MMAP
  uint64_t out_mapped;
#endif
  
  struct timespec start, stop, start_full, stop_full;
  
  if (argc < 4 || argc > 6)
    help();
  if (argc == 5 || argc == 6)
    assert(*argv[1] == 's');
  if (strlen(argv[1]) != 1)
    help();
  
  //file handling
  in = fopen(argv[2], "r");
  assert(in);

  out_fd = open(argv[3], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  assert(out_fd != -1);
  
  fstat(fileno(in), &st);
  full_len = st.st_size;
  
#ifdef USE_MMAP
  switch(argv[1][0]) {
    case 'e' : out_mapped = full_len*2;   break;
    case 'd' : out_mapped = CHUNK_SIZE*8; break;
    case 'm' : out_mapped = full_len; break;
  }
#endif
  
  //initialisation
#ifndef USE_MMAP_READ
  in_buf = malloc(CHUNK_SIZE);
#else
  in_map = mmap(NULL, full_len, PROT_READ, MAP_SHARED, fileno(in), 0);
  if (in_map == MAP_FAILED) {
    printf("WARNING: mmap failed for %s, using regular write\n", argv[2]);
    in_map = NULL;
    in_buf = malloc(2*CHUNK_SIZE);
  }
  else
    in_buf = in_map;
#endif
#ifndef USE_MMAP_WRITE
  out_buf = malloc(2*CHUNK_SIZE);
#else
  ftruncate(out_fd, out_mapped);
  out_map = mmap(NULL, out_mapped, PROT_WRITE, MAP_SHARED, out_fd, 0);
  if (out_map == MAP_FAILED) {
    printf("WARNING: mmap failed for %s, using regular write\n", argv[3]);
    out_map = NULL;
    out_buf = malloc(2*CHUNK_SIZE);
  }
  else
    out_buf = out_map;
#endif
  
  switch(argv[1][0]) {
#ifdef BBP_USE_SIMDCOMP
    case 'e' :
      clock_gettime(CLOCK_MONOTONIC, &start_full);
#ifndef USE_MMAP_READ
      while ((len = fread(in_buf, 1, CHUNK_SIZE, in))) {
#else
      for(in_buf=in_map;in_buf-in_map<full_len;in_buf+=CHUNK_SIZE) {
        len = full_len - (in_buf-in_map);
        if (len > CHUNK_SIZE)
          len = CHUNK_SIZE;
        if (len % (128*4))
          break;
#endif
        int b;
	clock_gettime(CLOCK_MONOTONIC, &start);
        //compression
        for(b=0;b<BENCHMARK_ITERATIONS;b++)
          len_c = compress(in_buf, len/4, out_buf);
	clock_gettime(CLOCK_MONOTONIC, &stop);
        time += ms_delta(start, stop);
	size += len;
	size_c += len_c;
        
        if (!out_map) {
          len = write(out_fd, out_buf, len_c);
          assert(len == len_c);
        }
        else
          out_buf += len_c;
      }
      out_len = size_c;
      
      clock_gettime(CLOCK_MONOTONIC, &stop_full);
      printf("compressed at %.3f MB/s / %.3fMB/s ratio %.2f\n",(float)size*BENCHMARK_ITERATIONS/1024/1024*1000/time, (float)size/1024/1024*1000/ms_delta(start_full, stop_full), (float)size/size_c);
      printf("%.2f %.3f simdcomp\n",(float)size/size_c, (float)size*BENCHMARK_ITERATIONS/1024/1024*1000/time);
      break;
#endif
#ifdef BBP_USE_SQUASH
    case 's' :
      assert(argc == 5 || argc == 6);
      SquashCodec* codec = squash_get_codec(argv[4]);
      SquashOptions *options;
      assert(codec);
      
      if (argc == 6) {
        options = squash_options_new(codec, NULL);
        ret = squash_options_parse_option(options, "level", argv[5]);
        if (ret != SQUASH_OK) {
          if (ret == SQUASH_BAD_PARAM) printf("ERROR: SQUASH: bad param\n");
          if (ret == SQUASH_BAD_VALUE) printf("ERROR: SQUASH: bad value\n");
          break;
        }
      }
      else
        options = NULL;
      
      clock_gettime(CLOCK_MONOTONIC, &start_full);
#ifndef USE_MMAP_READ
      while ((len = fread(in_buf, 1, CHUNK_SIZE, in))) {
#else
      for(in_buf=in_map;in_buf-in_map<full_len;in_buf+=CHUNK_SIZE) {
        len = full_len - (in_buf-in_map);
        if (len > CHUNK_SIZE)
          len = CHUNK_SIZE;
#endif
	clock_gettime(CLOCK_MONOTONIC, &start);
        //compression
        len_c = 2*CHUNK_SIZE;
        if (options)
          squash_codec_compress_with_options(codec, &len_c, out_buf, len, in_buf, options);
        else
          ret = squash_compress(argv[4], &len_c, out_buf, len, in_buf, NULL);
        if (ret != SQUASH_OK)
          printf("ERROR: SQUASH (%s): %s\n",squash_status_to_string(ret), argv[4]);
	clock_gettime(CLOCK_MONOTONIC, &stop);
        time += ms_delta(start, stop);
	size += len;
	size_c += len_c;
        
        if (!out_map) {
          len = write(out_fd, out_buf, len_c);
          assert(len == len_c);
        }
        else
          out_buf += len_c;
      }
      out_len = size_c;
      
      clock_gettime(CLOCK_MONOTONIC, &stop_full);
      printf("compressed at %.3fMB/s / %.3fMB/s ratio %.2f\n",(float)size/1024/1024*1000/time, (float)size/1024/1024*1000/ms_delta(start_full, stop_full), (float)size/size_c);
      printf("%.2f %.3f %s\n",(float)size/size_c, (float)size/1024/1024*1000/time, argv[4]);
      break;
#endif
  }
  
  if (in_map)
    munmap(in_map, full_len);
  fclose(in);
  
  if (out_map)
    munmap(out_map, full_len*2);
  ftruncate(out_fd, out_len);
  close(out_fd);

  
  return EXIT_SUCCESS;
}
예제 #5
0
static SquashStatus
squash_codec_process_file_with_options (SquashCodec* codec,
                                        SquashStreamType stream_type,
                                        FILE* output,
                                        size_t output_length,
                                        FILE* input,
                                        SquashOptions* options) {
  SquashStatus res = SQUASH_FAILED;
  SquashStream* stream;

  if (codec->impl.process_stream == NULL) {
    /* Attempt to mmap the input and output.  This short circuits the
       whole SquashBufferStream hack when possible, which can be a
       huge performance boost (50-100% for several codecs). */
    SquashMappedFile* in_map;

    in_map = squash_mapped_file_new (input, false);
    if (in_map != NULL) {
      SquashMappedFile* out_map;
      size_t max_output_size;

      if (stream_type == SQUASH_STREAM_COMPRESS) {
        max_output_size = squash_codec_get_max_compressed_size (codec, in_map->data_length);
      } else if (codec->impl.get_uncompressed_size != NULL) {
        max_output_size = squash_codec_get_uncompressed_size (codec, in_map->data_length, in_map->data);
      } else if (output_length != 0) {
        max_output_size = output_length;
      } else {
        max_output_size = in_map->data_length - 1;
        max_output_size |= max_output_size >> 1;
        max_output_size |= max_output_size >> 2;
        max_output_size |= max_output_size >> 4;
        max_output_size |= max_output_size >> 8;
        max_output_size |= max_output_size >> 16;
        max_output_size++;

        max_output_size <<= 3;
      }

      out_map = squash_mapped_file_new_full(output, false, 0, max_output_size);
      if (out_map != NULL) {
        size_t output_size = out_map->data_length;

        if (stream_type == SQUASH_STREAM_COMPRESS) {
          output_size = out_map->data_length;
          res = squash_codec_compress_with_options (codec, &output_size, out_map->data, in_map->data_length, in_map->data, options);
        } else {
          do {
            output_size = max_output_size;
            res = squash_codec_decompress_with_options (codec, &output_size, out_map->data, in_map->data_length, in_map->data, options);
            max_output_size <<= 1;
          } while (SQUASH_UNLIKELY(res == SQUASH_BUFFER_FULL) && output_length == 0 && codec->impl.get_uncompressed_size == NULL);
        }

        squash_mapped_file_free (out_map);
        out_map = NULL;

        /* We know that the mmap was successful, so not checking
           fileno() should be safe. */
        if (ftruncate (fileno (output), (off_t) output_size) == -1)
          res = SQUASH_FAILED;
        if (fseek (output, output_size, SEEK_SET) == -1)
          res = SQUASH_FAILED;
      }

      if (res != SQUASH_OK) {
        size_t ipos = in_map->data_offset;
        squash_mapped_file_free (in_map);
        fseek (input, ipos, SEEK_SET);
      } else {
        squash_mapped_file_free (in_map);
      }
      in_map = NULL;
    }