Функция сжатия в java для системы кэширования

#java #arrays #string #caching #compression

#java #массивы #строка #кэширование #сжатие

Вопрос:

Я создаю кеш, в котором должно храниться как можно больше данных. Процессор не является проблемой мэра, потому что следующий уровень данных намного более экспрессивен для достижения, чем запуск процессоров немного для распаковки.

Я ищу хорошую стратегию, а не полную реализацию. Типичный экземпляр объекта, который должен быть кэширован, может быть обобщен как список хэш-карт. Ключи в этой карте очень похожи на ключи в другой карте в этом списке. Ключи и значения являются строками.

Карты в разных объектах кэширования (это означает также разные списки) не всегда могут иметь одинаковые ключи. Возможно, только подмножество (50%) ключей одинаковы.

Я думал об извлечении ключей в ОДИН массив заголовков и каждой коллекции значений hashmap в другой массив с той же длиной. Это означает, что массив данных может быть разреженным (указатели на нуль). Но мне не нужно переносить метаданные. Расположение в массиве данных — единственный способ поиска правильного ключа.

Теперь я хочу сжать массив данных. Сжатие не будет хорошо работать с одним массивом данных, потому что информации мало. Для получения хорошей скорости сжатия потребуется несколько массивов данных, склеенных вместе.

Есть ли хороший способ сжатия строковых массивов в Java? Сколько из этих массивов данных я должен кластеризовать для получения хороших результатов?

Может быть, есть какой-нибудь лучший aporoach? Это открытые вопросы для сбора идей, поэтому, пожалуйста, не стесняйтесь уточнять 🙂

Комментарии:

1. Может быть, достаточно использовать интерн-строки для ключей? Не могли бы вы написать небольшой фрагмент кода для описания ваших структур данных? Описание не очень легко представить в моей голове.

Ответ №1:

Может помочь Flyweight

Если вы не сжимаете, вы можете использовать шаблон Flyweight, чтобы избежать стоимости строкового ключа, повторяющегося в каждом объекте.

Помните, что строка — это объект, поэтому ключ в вашей хэш-карте является ссылкой на него. Если множество объектов с одинаковым свойством используют ссылки на один и тот же строковый объект, у вас есть только 4 байта для каждой ссылки и только одна строка в памяти.

Как убедиться, что вы разделяете строковые объекты между объектами? Вы можете использовать что-то похожее на String.intern() . Но, пожалуйста, не используйте String.intern() сам.

Интернирование строки возвращает тот же объект string-object для того же строкового значения. Вы должны хранить кэш для этих строк. Причина, по которой я не рекомендую String.intern(), заключается в том, что кэш — это сам класс String, поэтому он никогда не освобождается. Но вы можете реализовать что-то аналогичное.

Этот код возвращает вашу собственную строку, если она новая. И возвращает первый, если это не так.

 HashMap<String,String> internedStrings = new HashMap<String,String>();

syncrhonized String returnUniqueString(String str) {
   String alreadyCached = internedStrings.get(str);
   if (alreadyCached == null) {
      internedStrings.put(str, str);
      alreadyCached = str;
   }
   return alreadyCached;
}
  

Но если вы сжимаете, не

Поскольку сжатие означает, что вы сериализуете свои объектные графики, и каждое имя свойства будет сериализовано как отдельная строка, поэтому повторяется. Возможно, сжатый размер не слишком сильно увеличивается, потому что это повторяющаяся строка, но при повторном преобразовании объектов они будут созданы отдельно.

Может быть, вы можете использовать returnUniqueString во время повторной проверки 🙂

Ответ №2:

Это звучит как хороший подход.

Тем не менее, я предлагаю вам рассмотреть другой способ разбиения значений карты на списки: вместо того, чтобы составлять список для каждой карты, создайте список для каждого отдельного ключа, содержащий значения для этого ключа для каждого элемента.

Например, если ваши карты:

 1: {
    colour: red,
    size: small,
},
2: {
    colour: blue,
    flavour: strawberry
},
3: {
    colour: red,
    size: large,
    flavour: strawberry
}
  

Затем вы разлагаетесь на:

 colour: [red, blue, red]
size: [small, null, large]
flavour: [null, strawberry, strawberry]
  

Это может показаться немного странным, но дело в том, что вы объединяете значения одного и того же типа вместе, что поможет сделать сжатие более эффективным.