blob: c137ef06f46a70f7027536539f235e5a149b6be1 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include <cstddef>
#include <memory>
#include "kudu/gutil/macros.h"
#include "kudu/gutil/ref_counted.h"
namespace kudu {
class Cache;
class Slice;
class Status;
namespace codegen {
class JITWrapper;
// A code cache is a specialized LRU cache with the following services:
// 1. It supports only one writer at a time, but multiple concurrent
// readers.
// 2. If its items are taking too much space, it evicts the least-
// recently-used member of the cache.
//
// The cache takes shared ownership of its entry values, the JITWrappers,
// by incrementing their reference count.
//
// LRU eviction does not guarantee that a JITWrapper is deleted, only that
// the cache releases its shared ownership (by decrementing the reference
// count) of the jit code.
class CodeCache {
public:
// TODO: currently CodeCache is implemented using the Cache in
// kudu/util/cache.h, which requires some transformation to nongeneric
// Slice-type keys and values. Furthermore, the Cache implementation
// provides concurrent write guarantees (thus relies on locks heavily), which
// is unnecessary for the CodeCache. A potential improvement would be to
// implement a single-writer multi-reader LRU cache with proper generics.
// TODO: a potential improvment would be for the cache to monitor its memory
// consumption explicity and keep its usage under a size limit specified at
// construction time. In order to do this, the cache would have to inject
// a custom memory manager into the CodeGenerator's execution engine which
// intercepts allocation calls and tracks code size.
// Generates an empty code cache which stores at most 'capacity' JITWrappers.
// A JIT payload is defined to be the combination of objects which rely on jitted
// code and the classes which own the jitted code.
explicit CodeCache(size_t capacity);
~CodeCache();
// This function is NOT thread safe (only one writer may call this at
// a time). Attempts to add a new entry 'wrapper' to the cache, using
// wrapper->EncodeOwnKey() as the key. Overwrites the previous value
// if one exists. If insertion results in excess capacity, LRU eviction
// occurs. Returns Status::OK() upon success.
Status AddEntry(const scoped_refptr<JITWrapper>& wrapper);
// This function may be called from any thread concurrently with other
// writes and reads to the cache. Looks in the cache for the specified key.
// Returns a reference to the associated payload, or NULL if no such entry
// exists in the cache.
scoped_refptr<JITWrapper> Lookup(const Slice& key);
private:
class EvictionCallback;
std::unique_ptr<EvictionCallback> eviction_callback_;
std::unique_ptr<Cache> cache_;
DISALLOW_COPY_AND_ASSIGN(CodeCache);
};
} // namespace codegen
} // namespace kudu