-
Notifications
You must be signed in to change notification settings - Fork 0
Fix: Clean up examples and unify request read signature #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @haochengxia, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request primarily focuses on refining the libCacheSim
Python binding's API for reading requests and overhauling its example documentation. The core change unifies the read_one_req
signature across different reader types, making the API more consistent and user-friendly. Concurrently, a significant cleanup of the example directory and the README.md
file has been performed to provide clearer, more up-to-date usage examples and remove outdated content.
Highlights
- API Unification for Request Reading: The
read_one_req
method acrossSyntheticReader
andTraceReader
has been updated to return aRequest
object directly, simplifying its usage by removing the need to pre-allocate and pass aRequest
object. - Comprehensive Example Overhaul: The entire
examples/
directory has been restructured and cleaned up. Outdated and redundant example scripts have been removed, and new, concise examples (basic_usage.py
,plugin_cache/s3fifo.py
) have been added to demonstrate core functionalities like trace processing and custom cache policy implementation. - README.md Modernization: The main
README.md
has been significantly updated to reflect the new API and examples. Obsolete sections (Documentation links, Features, Old Examples, Troubleshooting) have been removed, and new sections for trace processing withDataLoader
and a detailedPluginCache
example have been introduced. - Improved PluginCache Hook Signatures: The
PluginCache
hook functions (hit_hook
,miss_hook
,eviction_hook
) now receive aRequest
object directly, providing more comprehensive information about the current request within the custom policy logic.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request cleans up the examples and unifies the request reader signature across the library, which is a great simplification of the API. The changes involve removing old examples, adding new ones that reflect current best practices, and updating the README.
My review has identified a few issues:
- A critical bug in
TraceReader.__getitem__
and__next__
where it returns an incorrect type. - Several high-severity issues in the new examples, including incorrect cache size configurations for comparisons and logical errors in implementation that could lead to incorrect behavior or crashes.
- Some medium-severity issues in the README regarding clarity and typos, and a recommendation to add a test case for the
__getitem__
functionality to prevent future regressions.
def __getitem__(self, index: int) -> Request: | ||
if index < 0 or index >= self._reader.get_num_of_req(): | ||
raise IndexError("Index out of range") | ||
self._reader.reset() | ||
self._reader.skip_n_req(index) | ||
return self._reader.read_one_req() | ||
req = Request() | ||
return self._reader.read_one_req(req) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The __getitem__
method is implemented to return self._reader.read_one_req(req)
. Due to the changes in the C++ bindings, this call now returns an integer status code, not the Request
object. This means __getitem__
will incorrectly return an integer instead of a Request
instance, which violates its type hint and will break any code that uses it.
The req
object is populated by reference, so you should return req
after the call to _reader.read_one_req(req)
.
def __getitem__(self, index: int) -> Request: | |
if index < 0 or index >= self._reader.get_num_of_req(): | |
raise IndexError("Index out of range") | |
self._reader.reset() | |
self._reader.skip_n_req(index) | |
return self._reader.read_one_req() | |
req = Request() | |
return self._reader.read_one_req(req) | |
def __getitem__(self, index: int) -> Request: | |
if index < 0 or index >= self._reader.get_num_of_req(): | |
raise IndexError("Index out of range") | |
self._reader.reset() | |
self._reader.skip_n_req(index) | |
req = Request() | |
self._reader.read_one_req(req) | |
return req |
cache = lcs.S3FIFO(cache_size=1024*1024) | ||
obj_miss_ratio, byte_miss_ratio = cache.process_trace( | ||
reader, | ||
start_req=0, | ||
max_req=1000 | ||
) | ||
print(f"Object miss ratio: {obj_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reader
object is being reused for a second process_trace
call without being reset. After the first call, the reader's internal cursor will be at the end of the trace, so the second call will process zero requests, leading to misleading results.
You should call reader.reset()
before reusing it to ensure the trace is read from the beginning.
cache = lcs.S3FIFO(cache_size=1024*1024) | |
obj_miss_ratio, byte_miss_ratio = cache.process_trace( | |
reader, | |
start_req=0, | |
max_req=1000 | |
) | |
print(f"Object miss ratio: {obj_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}") | |
cache = lcs.S3FIFO(cache_size=1024*1024) | |
reader.reset() | |
obj_miss_ratio, byte_miss_ratio = cache.process_trace( | |
reader, | |
start_req=0, | |
max_req=1000 | |
) | |
print(f"Object miss ratio: {obj_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}") |
examples/plugin_cache/s3fifo.py
Outdated
def cache_eviction_hook(cache, request: Request): | ||
# NOTE(haocheng): never called | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cache_eviction_hook
is implemented as a no-op (pass
). According to the README.md
, this hook should return the object ID to evict. A pass
statement will cause the function to return None
, which will likely cause a runtime error in the C++ backend that expects an integer object ID.
The StandaloneS3FIFO
class has a cache_evict
method that seems to implement the correct eviction logic. This hook should probably call it.
def cache_eviction_hook(cache, request: Request): | |
# NOTE(haocheng): never called | |
pass | |
def cache_eviction_hook(cache, request: Request): | |
return cache.cache_evict() |
examples/plugin_cache/s3fifo.py
Outdated
cache_free_hook=cache_free_hook, | ||
cache_name="S3FIFO") | ||
|
||
ref_s3fifo = S3FIFO(cache_size=1024) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reference S3FIFO cache is initialized with a size of 1024
, while the plugin cache under test is initialized with 1024*1024
. For the comparison to be valid and for the assertion plugin_hit == ref_hit
to work correctly, both caches should have the same size.
ref_s3fifo = S3FIFO(cache_size=1024) | |
ref_s3fifo = S3FIFO(cache_size=1024*1024) |
print(f"Object miss ratio: {obj_miss_ratio:.4f}, Byte miss ratio: {byte_miss_ratio:.4f}") | ||
``` | ||
|
||
> [!NOTE] | ||
> We DO NOT ignore the object size by defaults, you can add `reader_init_params = lcs.ReaderInitParam(ignore_obj_size=False)` to the initialization of `TraceReader` if needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The note about ignore_obj_size
is a bit confusing. It states that the default is not to ignore object size (i.e., ignore_obj_size=False
), and then suggests adding reader_init_params = lcs.ReaderInitParam(ignore_obj_size=False)
if needed, which is redundant.
A clearer explanation would be more helpful for users, for instance, explaining when they might want to set it to True
.
> We DO NOT ignore the object size by defaults, you can add `reader_init_params = lcs.ReaderInitParam(ignore_obj_size=False)` to the initialization of `TraceReader` if needed. | |
To ignore object sizes, add `reader_init_params = lcs.ReaderInitParam(ignore_obj_size=True)` to the `TraceReader` initialization. This can improve performance when object sizes are irrelevant. |
README.md
Outdated
- Educational purposes and learning | ||
- Research and experimentation | ||
- Custom business logic implementation | ||
The `PluginCache` allows you to define custom caching behavior through Python callback functions without without any C/C++ compilation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a typo here: "without without".
The `PluginCache` allows you to define custom caching behavior through Python callback functions without without any C/C++ compilation. | |
The `PluginCache` allows you to define custom caching behavior through Python callback functions without any C/C++ compilation. |
No description provided.