На каких языках поддерживается кэширование возвращаемых значений без стандартного кода? - PullRequest
5 голосов
/ 21 мая 2009

Для методов, где ...

  • существует статическое взаимно-однозначное отображение между входом и выходом, а
  • стоимость создания выходного объекта относительно высока, а
  • метод вызывается повторно с одним и тем же входом

... необходимо кэшировать значения результатов.

В моем коде следующий шаблон кэширования значения результата многократно повторяется (псевдокод в Java, но вопрос не зависит от языка):

private static Map<Input, Output> fooResultMap = new HashMap<Input, Output>();
public getFoo(Input input) {
  if (fooResultMap.get(input) != null) {
    return fooResultMap.get(input);
  }
  Output output = null;
  // Some code to obtain the object since we don't have it in the cache.
  fooResultMap.put(input, output);
  return output;
}

Постоянное повторение этой структуры является явным нарушением принципа СУХОЙ.

В идеале я бы хотел, чтобы приведенный выше код был сокращен до следующего:

@CacheResult
public getFoo(Input input) {
  Output output = null;
  // Some code to obtain the object since we don't have it in the cache.
  return output;
}

Где теоретическая аннотация CacheResult позаботится о кэшировании, которое я сейчас выполняю вручную.

Общий термин для этого типа кэширования: " памятка ".

Хороший пример точной функциональности, которую я ищу, - Модуль ядра Perl "Memoize" .

На каких языках существует такое решение кэширования, подобное Memoize (либо на уровне языка, либо на уровне библиотеки)? В частности - существует ли такое решение для какой-либо крупной платформы, такой как Java или .NET?

Ответы [ 9 ]

4 голосов
/ 21 мая 2009

Не встроенный язык, поместите модуль CPAN Памятка достаточно популярна в Perl, я думаю:

   # Compute Fibonacci numbers
    sub fib {
      my $n = shift;
      return $n if $n < 2;
      fib($n-1) + fib($n-2);
    }

    use Memoize;
    memoize('fib');
2 голосов
/ 11 ноября 2009

Обработчик кэширования - в .Net 'Enterprise Library'

http://msdn.microsoft.com/en-us/library/cc511757.aspx

[CachingCallHandler(0, 0, 30)]
public decimal GetSavingsBalance(int accountNumber)
{
  // Code here to extract balance from database.
  return balance;
}
1 голос
/ 22 мая 2009

Область инкубации Spring, springmodules имеет именно эту функциональность для Java.

Кэш Springmodules все еще на уровне релиза 0.8, но в целом он работал довольно хорошо, когда я попробовал его в прошлом году. Существуют параметры для настройки кэширования в файлах конфигурации Spring, а также с помощью аннотаций, что очень похоже на ваш пример. Из их документов:

public class TigerCacheableService implements CacheableService {

  @Cacheable(modelId = "testCaching")
  public final String getName(int index) {
    // some implementation.
  }
...
}

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

1 голос
/ 21 мая 2009

Python имеет несколько рецептов декоратора, например, модуль декоратора , который работает для этого (, если все параметры неизменны), и он имеет реализации как на JVM, так и .NET.

0 голосов
/ 21 мая 2009

Microsoft T-SQL может кэшировать возвращаемые значения из функции CLR на pr. база запросов ...

(Нет шаблона, кроме правильных атрибутов метода при записи в CLR.)

0 голосов
/ 21 мая 2009

Этот вопрос / ответ адресован Memoization в C #. Он не кэширует результаты, но его можно легко изменить, чтобы сделать карту статичной с помощью ReaderWriterLock.

Вот пример из ссылки , приведенной :

public static Func<A, R> Memoize<A, R>(this Func<A, R> f)
{
  var map = new Dictionary<A, R>();
  return a =>
    {
      R value;
      if (map.TryGetValue(a, out value))
        return value;
      value = f(a);
      map.Add(a, value);
      return value;
    };
}
0 голосов
/ 21 мая 2009

Вы можете реализовать аннотацию @CacheResult в Java, используя, например, ASM в transform метод для добавления кода памятки.

0 голосов
/ 21 мая 2009

Можно выделить такой код в Java, хотя синтаксис Java остается многословным

private static final Cache<Input, Output> fooCache = Caches.newInstance(
    new Factory<Input, Output>() { public Output create(Input input) {
        return ... some code ...;
    }}
);
public static Output getFoo(Input input) {
    return fooCache.get(input);
}

С улучшенной синтаксической поддержкой анонимных внутренних классов, которые могут стать, скажем:

private static final Cache<Input, Output> fooCache =
    (Input input) (... some code ...);
public static Output getFoo(Input input) {
    return fooCache.get(input);
}

Это единственное, что может сделать решение АОП, за счет того, что приходится иметь дело с небольшим количеством магии.

0 голосов
/ 21 мая 2009

Не является прямым ответом на ваш вопрос, но если вы поддерживаете много кешей, возможно, стоит использовать OSCache (Java) для управления этими кешами. Исключение устаревших объектов и т. Д. Становится проблемой, о которой вам не о чем беспокоиться.

Вам все равно придется использовать базовый шаблон «проверить кэш», «вернуть в кэш» или «создать и добавить в кэш».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...