Skip to content
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

refactor: 调整className hash算法, 降低哈希碰撞概率(已经出现了) #856

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

saint3347
Copy link
Collaborator

@saint3347 saint3347 commented Dec 6, 2024

Types of changes

  • New feature
  • Bug fix
  • Site / documentation update
  • Demo update
  • Component style update
  • TypeScript definition update
  • Bundle size optimization
  • Performance optimization
  • Enhancement feature
  • Internationalization
  • Refactoring
  • Code style optimization
  • Test Case
  • Branch merge
  • Workflow
  • Others

Background

'soui-button-button'和'soui-datePicker-day-picker'这两个className在3.5.4-beta.6时计算出的哈希碰撞了

Changelog

  • 调整className hash算法, 降低哈希碰撞概率,同时增加计算结果的缓存

Summary by CodeRabbit

  • 新功能
    • 优化了字符串哈希生成的效率,通过缓存机制减少重复计算。
  • bug修复
    • 主按钮组件的text属性被移除,确保按钮的渲染符合预期。

Copy link

coderabbitai bot commented Dec 6, 2024

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • packages/shineout/src/button/__test__/__snapshots__/button.spec.tsx.snap is excluded by !**/*.snap

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

此次更改涉及两个主要文件的修改。首先,在 shineout-style 包的 index.tsx 文件中,新增了 hashCache 对象以缓存字符串的哈希值,并优化了 stringToHash 函数的逻辑。该函数现在会优先检查缓存中的哈希值,从而提高效率。其次,在 shineout 包的 s-001-base.tsx 文件中,主要按钮的 text 属性被移除,其他按钮类型保持不变。

Changes

文件路径 更改摘要
packages/shineout-style/src/jss-style/index.tsx 添加 hashCache 对象,修改 stringToHash 函数逻辑以使用缓存,更新 generateClassNamecreateClassname 函数的逻辑,新增类型别名 JsStylesClassStyle
packages/shineout/src/button/example/s-001-base.tsx 移除主要按钮的 text 属性,保持其他按钮类型不变。

Poem

在风中跳跃的小兔子,
新变更如花儿盛开,
哈希缓存真神奇,
按钮简洁又可爱。
代码更新真欢快,
一起欢庆这变化! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
packages/shineout-style/src/jss-style/index.tsx (1)

23-29: 改进:使用更强大的哈希算法

新的哈希算法实现有以下优点:

  1. 使用 BigInt 处理大数运算,避免精度损失
  2. 使用位运算提高散列效果
  3. 限制在64位范围内,保证稳定性

建议添加算法的注释说明,方便后续维护。

 let hash = BigInt(0);
 if (str.length === 0) return '';
+// 使用改进的FNV-1a哈希算法
 for (let i = 0; i < str.length; i += 1) {
   const char = BigInt(str.charCodeAt(i));
   hash = (hash << BigInt(5)) - hash + char;
   hash &= BigInt('0xFFFFFFFFFFFFFFFF'); // 限制在64位整数范围内
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 823a6ba and 95915e5.

📒 Files selected for processing (2)
  • packages/shineout-style/src/jss-style/index.tsx (1 hunks)
  • packages/shineout/src/button/__example__/s-001-base.tsx (1 hunks)
🔇 Additional comments (3)
packages/shineout/src/button/__example__/s-001-base.tsx (1)

16-16: 代码变更正确!

移除主按钮的 text 属性使示例更加清晰,更好地展示了按钮的基本用法。

packages/shineout-style/src/jss-style/index.tsx (2)

17-21: 优化:使用缓存提高性能

引入 hashCache 缓存可以避免重复计算哈希值,这是一个很好的性能优化。对于经常重复使用的类名来说,这个优化特别有效。


30-32: 安全性改进:确保生成有效的CSS类名

通过添加 'c' 前缀确保生成的哈希值始终是有效的CSS类名,这是一个很好的安全实践。

建议添加单元测试验证哈希碰撞率。

✅ Verification successful

Let me verify the hash function implementation and its usage in the codebase.


哈希算法实现安全且有效

基于代码分析和碰撞测试结果,可以确认:

  1. 哈希算法实现使用了 BigInt 确保了64位整数范围内的计算精度
  2. 通过 hashCache 缓存优化了性能
  3. 添加 'c' 前缀确保了生成的类名符合 CSS 命名规范
  4. 碰撞测试显示在 1233 个实际类名中碰撞率为 0%

建议:

  • 可以保持当前实现,无需添加额外的单元测试,因为实际使用数据已经验证了其可靠性
  • 建议在代码注释中说明哈希算法的设计考虑,方便后续维护
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 验证新哈希算法的碰撞率

# 搜索所有使用到的类名
rg -o "soui-[a-zA-Z0-9-]+" | sort | uniq > class_names.txt

# 使用新算法计算哈希值并检查碰撞
node << 'EOF'
const fs = require('fs');
const classNames = fs.readFileSync('class_names.txt', 'utf8').split('\n');
const hashes = new Map();
let collisions = 0;

classNames.forEach(name => {
  let hash = BigInt(0);
  for (let i = 0; i < name.length; i++) {
    const char = BigInt(name.charCodeAt(i));
    hash = (hash << BigInt(5)) - hash + char;
    hash &= BigInt('0xFFFFFFFFFFFFFFFF');
  }
  const hashStr = 'c' + hash.toString(36);
  
  if (hashes.has(hashStr)) {
    console.log(`碰撞: ${name} 与 ${hashes.get(hashStr)}`);
    collisions++;
  }
  hashes.set(hashStr, name);
});

console.log(`总类名数: ${classNames.length}`);
console.log(`碰撞数: ${collisions}`);
console.log(`碰撞率: ${(collisions/classNames.length*100).toFixed(2)}%`);
EOF

Length of output: 78


Script:

#!/bin/bash
# 检查哈希函数的实现和使用
ast-grep --pattern 'function hash($$$) {
  $$$
}'

# 查找哈希函数的调用位置
rg "hash\(" -A 2

# 检查是否有相关的测试文件
fd "hash.*test" 

Length of output: 362


Script:

#!/bin/bash
# 检查哈希函数的具体实现
rg -B 5 -A 10 "function hash" 

# 检查是否有其他生成类名的方式
rg "className|class=" -A 2

# 检查当前的哈希缓存实现
ast-grep --pattern 'const hashCache = {
  $$$
}'

Length of output: 118286


Script:

#!/bin/bash
# 检查哈希函数的完整实现和使用
rg -B 10 -A 10 "const hashCache = " packages/shineout-style/src/jss-style/index.tsx

# 检查是否有相关的测试文件
fd "jss-style.*test"

# 检查哈希值的使用情况
rg "hash\(" packages/shineout-style/src/

Length of output: 151


Script:

#!/bin/bash
# 检查文件内容
cat packages/shineout-style/src/jss-style/index.tsx

# 检查是否有其他相关实现
rg -g "*.{ts,tsx,js,jsx}" "function hash" 

# 检查哈希值的使用情况
rg -g "*.{ts,tsx,js,jsx}" "hashCache" 

Length of output: 3207

@renaesop renaesop requested a review from Copilot December 12, 2024 02:23

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 2 out of 3 changed files in this pull request and generated no suggestions.

Files not reviewed (1)
  • packages/shineout/src/button/test/snapshots/button.spec.tsx.snap: Language not supported
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant