diff --git a/src/vanilla/utils/proxyMap.ts b/src/vanilla/utils/proxyMap.ts
index 6fc3a9c0..40950b02 100644
--- a/src/vanilla/utils/proxyMap.ts
+++ b/src/vanilla/utils/proxyMap.ts
@@ -1,111 +1,149 @@
-import { proxy } from '../../vanilla.ts'
+import { proxy, unstable_getInternalStates } from '../../vanilla.ts'
 
-type KeyValRecord<K, V> = [key: K, value: V]
+const { proxyStateMap, snapCache } = unstable_getInternalStates()
+const isProxy = (x: any) => proxyStateMap.has(x)
 
-type InternalProxyMap<K, V> = Map<K, V> & {
-  data: KeyValRecord<K, V>[]
-  toJSON: object
+type InternalProxyObject<K, V> = Map<K, V> & {
+  data: Array<V>
+  index: number
+  toJSON: () => Map<K, V>
 }
 
-/**
- * proxyMap
- *
- * This is to create a proxy which mimic the native Map behavior.
- * The API is the same as Map API
- *
- * @example
- * import { proxyMap } from 'valtio/utils'
- * const state = proxyMap([["key", "value"]])
- *
- * //can be used inside a proxy as well
- * const state = proxy({
- *   count: 1,
- *   map: proxyMap()
- * })
- *
- * // When using an object as a key, you can wrap it with `ref` so it's not proxied
- * // this is useful if you want to preserve the key equality
- * import { ref } from 'valtio'
- *
- * const key = ref({})
- * state.set(key, "value")
- * state.get(key) //value
- *
- * const key = {}
- * state.set(key, "value")
- * state.get(key) //undefined
- */
-export function proxyMap<K, V>(entries?: Iterable<readonly [K, V]> | null) {
-  const map: InternalProxyMap<K, V> = proxy({
-    data: Array.from(entries || []) as KeyValRecord<K, V>[],
-    has(key) {
-      return this.data.some((p) => p[0] === key)
+export function proxyMap<K, V>(entries?: Iterable<[K, V]> | undefined | null) {
+  const initialData: Array<V> = []
+  let initialIndex = 0
+  const indexMap = new Map<K, number>()
+
+  const snapMapCache = new WeakMap<object, Map<K, number>>()
+  const registerSnapMap = () => {
+    const cache = snapCache.get(vObject)
+    const latestSnap = cache?.[1]
+    if (latestSnap && !snapMapCache.has(latestSnap)) {
+      const clonedMap = new Map(indexMap)
+      snapMapCache.set(latestSnap, clonedMap)
+    }
+  }
+  const getMapForThis = (x: any) => snapMapCache.get(x) || indexMap
+
+  if (entries) {
+    if (typeof entries[Symbol.iterator] !== 'function') {
+      throw new TypeError(
+        'proxyMap:\n\tinitial state must be iterable\n\t\ttip: structure should be [[key, value]]',
+      )
+    }
+    for (const [key, value] of entries) {
+      indexMap.set(key, initialIndex)
+      initialData[initialIndex++] = value
+    }
+  }
+
+  const vObject: InternalProxyObject<K, V> = {
+    data: initialData,
+    index: initialIndex,
+    get size() {
+      if (!isProxy(this)) {
+        registerSnapMap()
+      }
+      const map = getMapForThis(this)
+      return map.size
+    },
+    get(key: K) {
+      const map = getMapForThis(this)
+      const index = map.get(key)
+      if (index === undefined) {
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+        this.index // touch property for tracking
+        return undefined
+      }
+      return this.data[index]
+    },
+    has(key: K) {
+      const map = getMapForThis(this)
+      const exists = map.has(key)
+      if (!exists) {
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+        this.index // touch property for tracking
+      }
+      return exists
     },
-    set(key, value) {
-      const record = this.data.find((p) => p[0] === key)
-      if (record) {
-        record[1] = value
+    set(key: K, value: V) {
+      if (!isProxy(this)) {
+        throw new Error('Cannot perform mutations on a snapshot')
+      }
+      const index = indexMap.get(key)
+      if (index === undefined) {
+        indexMap.set(key, this.index)
+        this.data[this.index++] = value
       } else {
-        this.data.push([key, value])
+        this.data[index] = value
       }
       return this
     },
-    get(key) {
-      return this.data.find((p) => p[0] === key)?.[1]
-    },
-    delete(key) {
-      const index = this.data.findIndex((p) => p[0] === key)
-      if (index === -1) {
+    delete(key: K) {
+      if (!isProxy(this)) {
+        throw new Error('Cannot perform mutations on a snapshot')
+      }
+      const index = indexMap.get(key)
+      if (index === undefined) {
         return false
       }
-      this.data.splice(index, 1)
+      delete this.data[index]
+      indexMap.delete(key)
       return true
     },
     clear() {
-      this.data.splice(0)
-    },
-    get size() {
-      return this.data.length
-    },
-    toJSON() {
-      return new Map(this.data)
-    },
-    forEach(cb) {
-      this.data.forEach((p) => {
-        cb(p[1], p[0], this)
+      if (!isProxy(this)) {
+        throw new Error('Cannot perform mutations on a snapshot')
+      }
+      this.data.length = 0 // empty array
+      this.index = 0
+      indexMap.clear()
+    },
+    forEach(cb: (value: V, key: K, map: Map<K, V>) => void) {
+      const map = getMapForThis(this)
+      map.forEach((index, key) => {
+        cb(this.data[index]!, key, this)
       })
     },
-    keys() {
-      return this.data.map((p) => p[0]).values()
-    },
-    values() {
-      return this.data.map((p) => p[1]).values()
+    *entries(): MapIterator<[K, V]> {
+      const map = getMapForThis(this)
+      for (const [key, index] of map) {
+        yield [key, this.data[index]!]
+      }
     },
-    entries() {
-      return new Map(this.data).entries()
+    *keys(): IterableIterator<K> {
+      const map = getMapForThis(this)
+      for (const key of map.keys()) {
+        yield key
+      }
     },
-    get [Symbol.toStringTag]() {
-      return 'Map'
+    *values(): IterableIterator<V> {
+      const map = getMapForThis(this)
+      for (const index of map.values()) {
+        yield this.data[index]!
+      }
     },
     [Symbol.iterator]() {
       return this.entries()
     },
-  })
-
-  Object.defineProperties(map, {
-    data: {
-      enumerable: false,
-    },
-    size: {
-      enumerable: false,
+    get [Symbol.toStringTag]() {
+      return 'Map'
     },
-    toJSON: {
-      enumerable: false,
+    toJSON(): Map<K, V> {
+      return new Map(this.entries())
     },
+  }
+
+  const proxiedObject = proxy(vObject)
+  Object.defineProperties(proxiedObject, {
+    size: { enumerable: false },
+    index: { enumerable: false },
+    data: { enumerable: false },
+    toJSON: { enumerable: false },
   })
-  Object.seal(map)
+  Object.seal(proxiedObject)
 
-  return map as unknown as Map<K, V> & {
+  return proxiedObject as unknown as Map<K, V> & {
     $$valtioSnapshot: Omit<Map<K, V>, 'set' | 'delete' | 'clear'>
   }
 }
diff --git a/src/vanilla/utils/proxySet.ts b/src/vanilla/utils/proxySet.ts
index 575d218c..7ba52119 100644
--- a/src/vanilla/utils/proxySet.ts
+++ b/src/vanilla/utils/proxySet.ts
@@ -1,98 +1,195 @@
-import { proxy } from '../../vanilla.ts'
+import { proxy, unstable_getInternalStates } from '../../vanilla.ts'
+
+const { proxyStateMap, snapCache } = unstable_getInternalStates()
+const maybeProxify = (x: any) => (typeof x === 'object' ? proxy({ x }).x : x)
+const isProxy = (x: any) => proxyStateMap.has(x)
 
-// properties that we don't want to expose to the end-user
 type InternalProxySet<T> = Set<T> & {
   data: T[]
   toJSON: object
+  index: number
+  intersection: (other: Set<T>) => Set<T>
+  isDisjointFrom: (other: Set<T>) => boolean
+  isSubsetOf: (other: Set<T>) => boolean
+  isSupersetOf: (other: Set<T>) => boolean
+  symmetricDifference: (other: Set<T>) => Set<T>
+  union: (other: Set<T>) => Set<T>
 }
 
-/**
- * proxySet
- *
- * This is to create a proxy which mimic the native Set behavior.
- * The API is the same as Set API
- *
- * @example
- * import { proxySet } from 'valtio/utils'
- * const state = proxySet([1,2,3])
- * //can be used inside a proxy as well
- * const state = proxy({
- *   count: 1,
- *   set: proxySet()
- * })
- */
 export function proxySet<T>(initialValues?: Iterable<T> | null) {
-  const set: InternalProxySet<T> = proxy({
-    data: Array.from(new Set(initialValues)),
-    has(value) {
-      return this.data.indexOf(value) !== -1
-    },
-    add(value) {
-      let hasProxy = false
-      if (typeof value === 'object' && value !== null) {
-        hasProxy = this.data.indexOf(proxy(value as T & object)) !== -1
+  const initialData: T[] = []
+  const indexMap = new Map<T, number>()
+  let initialIndex = 0
+
+  const snapMapCache = new WeakMap<object, Map<T, number>>()
+  const registerSnapMap = () => {
+    const cache = snapCache.get(vObject)
+    const latestSnap = cache?.[1]
+    if (latestSnap && !snapMapCache.has(latestSnap)) {
+      const clonedMap = new Map(indexMap)
+      snapMapCache.set(latestSnap, clonedMap)
+    }
+  }
+  const getMapForThis = (x: any) => snapMapCache.get(x) || indexMap
+
+  if (initialValues) {
+    if (typeof initialValues[Symbol.iterator] !== 'function') {
+      throw new TypeError('not iterable')
+    }
+    for (const value of initialValues) {
+      if (!indexMap.has(value)) {
+        const v = maybeProxify(value)
+        indexMap.set(v, initialIndex)
+        initialData[initialIndex++] = v
       }
-      if (this.data.indexOf(value) === -1 && !hasProxy) {
-        this.data.push(value)
+    }
+  }
+
+  const vObject: InternalProxySet<T> = {
+    data: initialData,
+    index: initialIndex,
+    get size() {
+      if (!isProxy(this)) {
+        registerSnapMap()
+      }
+      return indexMap.size
+    },
+    has(value: T) {
+      const map = getMapForThis(this)
+      const v = maybeProxify(value)
+      const exists = map.has(v)
+      if (!exists) {
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+        this.index // touch property for tracking
+      }
+      return exists
+    },
+    add(value: T) {
+      if (!isProxy(this)) {
+        throw new Error('Cannot perform mutations on a snapshot')
+      }
+      const v = maybeProxify(value)
+      if (!indexMap.has(v)) {
+        indexMap.set(v, this.index)
+        this.data[this.index++] = v
       }
       return this
     },
-    delete(value) {
-      const index = this.data.indexOf(value)
-      if (index === -1) {
+    delete(value: T) {
+      if (!isProxy(this)) {
+        throw new Error('Cannot perform mutations on a snapshot')
+      }
+      const v = maybeProxify(value)
+      const index = indexMap.get(v)
+      if (index === undefined) {
         return false
       }
-      this.data.splice(index, 1)
+      delete this.data[index]
+      indexMap.delete(v)
       return true
     },
     clear() {
-      this.data.splice(0)
-    },
-    get size() {
-      return this.data.length
+      if (!isProxy(this)) {
+        throw new Error('Cannot perform mutations on a snapshot')
+      }
+      this.data.length = 0 // empty array
+      this.index = 0
+      indexMap.clear()
     },
     forEach(cb) {
-      this.data.forEach((value) => {
-        cb(value, value, this)
+      const map = getMapForThis(this)
+      map.forEach((index) => {
+        cb(this.data[index]!, this.data[index]!, this)
       })
     },
-    get [Symbol.toStringTag]() {
-      return 'Set'
+    *values(): IterableIterator<T> {
+      const map = getMapForThis(this)
+      for (const index of map.values()) {
+        yield this.data[index]!
+      }
+    },
+    keys(): IterableIterator<T> {
+      return this.values()
+    },
+    *entries(): IterableIterator<[T, T]> {
+      const map = getMapForThis(this)
+      for (const index of map.values()) {
+        const value = this.data[index]!
+        yield [value, value]
+      }
     },
-    toJSON() {
-      return new Set(this.data)
+    toJSON(): Set<T> {
+      return new Set(this.values())
     },
     [Symbol.iterator]() {
-      return this.data[Symbol.iterator]()
+      return this.values()
     },
-    values() {
-      return this.data.values()
+    get [Symbol.toStringTag]() {
+      return 'Set'
     },
-    keys() {
-      // for Set.keys is an alias for Set.values()
-      return this.data.values()
+    intersection(other: Set<T>): Set<T> {
+      const otherSet = proxySet<T>(other)
+      const resultSet = proxySet<T>()
+      for (const value of this.values()) {
+        if (otherSet.has(value)) {
+          resultSet.add(value)
+        }
+      }
+      return proxySet(resultSet)
     },
-    entries() {
-      // array.entries returns [index, value] while Set [value, value]
-      return new Set(this.data).entries()
+    isDisjointFrom(other: Set<T>): boolean {
+      const otherSet = proxySet<T>(other)
+      return (
+        this.size === other.size &&
+        [...this.values()].every((value) => !otherSet.has(value))
+      )
     },
-  })
-
-  Object.defineProperties(set, {
-    data: {
-      enumerable: false,
+    isSubsetOf(other: Set<T>) {
+      const otherSet = proxySet<T>(other)
+      return (
+        this.size <= other.size &&
+        [...this.values()].every((value) => otherSet.has(value))
+      )
     },
-    size: {
-      enumerable: false,
+    isSupersetOf(other: Set<T>) {
+      const otherSet = proxySet<T>(other)
+      return (
+        this.size >= other.size &&
+        [...otherSet].every((value) => this.has(value))
+      )
     },
-    toJSON: {
-      enumerable: false,
+    symmetricDifference(other: Set<T>) {
+      const resultSet = proxySet<T>()
+      const otherSet = proxySet<T>(other)
+      for (const value of this.values()) {
+        if (!otherSet.has(value)) {
+          resultSet.add(value)
+        }
+      }
+      return proxySet(resultSet)
     },
-  })
+    union(other: Set<T>) {
+      const resultSet = proxySet<T>()
+      const otherSet = proxySet<T>(other)
+      for (const value of this.values()) {
+        resultSet.add(value)
+      }
+      for (const value of otherSet) {
+        resultSet.add(value)
+      }
+      return proxySet(resultSet)
+    },
+  }
 
-  Object.seal(set)
+  const proxiedObject = proxy(vObject)
+  Object.defineProperties(proxiedObject, {
+    size: { enumerable: false },
+    data: { enumerable: false },
+    toJSON: { enumerable: false },
+  })
+  Object.seal(proxiedObject)
 
-  return set as unknown as Set<T> & {
-    $$valtioSnapshot: Omit<Set<T>, 'add' | 'delete' | 'clear'>
+  return proxiedObject as unknown as InternalProxySet<T> & {
+    $$valtioSnapshot: Omit<InternalProxySet<T>, 'set' | 'delete' | 'clear'>
   }
 }
diff --git a/tests/proxyMap.bench.ts b/tests/proxyMap.bench.ts
new file mode 100644
index 00000000..8a6bacf4
--- /dev/null
+++ b/tests/proxyMap.bench.ts
@@ -0,0 +1,150 @@
+/* eslint-disable vitest/consistent-test-it */
+import { bench, describe, test } from 'vitest'
+import { proxy, snapshot } from 'valtio'
+import { proxyMap } from 'valtio/utils'
+
+// Helper function to generate test data
+function generateTestData(size: number): [number, number][] {
+  const data: [any, any][] = []
+  for (let i = 0; i < size; i++) {
+    data.push([{ id: i }, { i }])
+  }
+  return data
+}
+
+const TEST_SIZES = [1000, 10_000, 100_000]
+
+TEST_SIZES.forEach((size) => {
+  describe.skip(`Insertion -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>()
+      testData.forEach(([key, value]) => {
+        map.set(key, value)
+      })
+    })
+  })
+
+  describe.skip(`Insertion and Update -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>()
+      testData.forEach(([key, value]) => {
+        map.set(key, value)
+        map.set(key, -1)
+      })
+    })
+  })
+
+  describe.skip(`Retrieval -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      testData.forEach(([key]) => {
+        map.get(key)
+      })
+    })
+  })
+
+  describe.skip(`Deletion -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      testData.forEach(([key]) => {
+        map.delete(key)
+      })
+    })
+  })
+
+  describe.skip(`Iteration -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      testData.forEach(([key, value]) => {})
+    })
+  })
+
+  describe.skip(`Insertion, Retrieval, and Deletion -${size} items`, () => {
+    const testData = generateTestData(size)
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      testData.forEach(([key, value]) => {
+        map.set(key, value)
+        map.get(key)
+        map.delete(key)
+      })
+    })
+  })
+
+  describe.skip(`entries -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      for (const [k, v] of map.entries()) {
+        const _k = k
+        const _v = v
+      }
+    })
+  })
+
+  describe.skip(`keys -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      for (const k of map.keys()) {
+        const _k = k
+      }
+    })
+  })
+
+  describe.skip(`values -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      for (const v of map.values()) {
+        const _v = v
+      }
+    })
+  })
+
+  describe.skip(`snapshot -${size} items`, () => {
+    const testData = generateTestData(size)
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      const snap = snapshot(map)
+      testData.forEach(([key, value]) => {
+        snap.get(key)
+      })
+    })
+  })
+
+  describe(`snapshot & modify -${size} items`, () => {
+    const testData = generateTestData(size)
+    const oneData = generateTestData(1)[0]!
+
+    bench('proxyMap', () => {
+      const map = proxyMap<number, number>(testData)
+      const snap1 = snapshot(map)
+      map.set(oneData[0], oneData[1])
+      const snap2 = snapshot(map)
+    })
+  })
+
+  describe.skip('Clear -${size} items', () => {
+    const testData = generateTestData(size)
+    const map = proxyMap<number, number>(testData)
+
+    bench('proxyMap', () => {
+      map.clear()
+    })
+  })
+})
diff --git a/tests/proxyMap.test.tsx b/tests/proxyMap.test.tsx
index 8b5955df..b0aa959b 100644
--- a/tests/proxyMap.test.tsx
+++ b/tests/proxyMap.test.tsx
@@ -319,8 +319,23 @@ describe('proxyMap internal', () => {
     ).toBe(false)
   })
 })
-
 describe('snapshot', () => {
+  it('should error when trying to mutate a snapshot', () => {
+    const state = proxyMap()
+    const snap = snapshot(state)
+
+    // @ts-expect-error - snapshot should not be able to mutate
+    expect(() => snap.set('foo', 'bar')).toThrow(
+      'Cannot perform mutations on a snapshot',
+    )
+    // @ts-expect-error - snapshot should not be able to mutate
+    expect(() => snap.delete('foo')).toThrow(
+      'Cannot perform mutations on a snapshot',
+    )
+    // @ts-expect-error - snapshot should not be able to mutate
+    expect(() => snap.clear()).toThrow('Cannot perform mutations on a snapshot')
+  })
+
   it('should not change snapshot with modifying the original proxy', async () => {
     const state = proxyMap([
       ['key1', {}],
diff --git a/tests/proxySet.test.tsx b/tests/proxySet.test.tsx
index 74d1db39..8ff894a9 100644
--- a/tests/proxySet.test.tsx
+++ b/tests/proxySet.test.tsx
@@ -1,7 +1,7 @@
 import { StrictMode } from 'react'
 import { fireEvent, render, waitFor } from '@testing-library/react'
 import { describe, expect, it, vi } from 'vitest'
-import { proxy, useSnapshot } from 'valtio'
+import { proxy, snapshot, useSnapshot } from 'valtio'
 import { proxySet } from 'valtio/utils'
 
 // used to initialize proxySet during tests
@@ -335,3 +335,33 @@ describe('proxySet internal', () => {
     ).toBe(false)
   })
 })
+
+describe('snapshot behavior', () => {
+  it('should error when trying to mutate a snapshot', () => {
+    const state = proxySet()
+    const snap = snapshot(state)
+
+    expect(() => snap.add('foo')).toThrow(
+      'Cannot perform mutations on a snapshot',
+    )
+    // @ts-expect-error - snapshot should not be able to mutate
+    expect(() => snap.delete('foo')).toThrow(
+      'Cannot perform mutations on a snapshot',
+    )
+    // @ts-expect-error - snapshot should not be able to mutate
+    expect(() => snap.clear()).toThrow('Cannot perform mutations on a snapshot')
+  })
+
+  it('should work with deleting a key', async () => {
+    const state = proxySet(['val1', 'val2'])
+    const snap1 = snapshot(state)
+    expect(snap1.has('val1')).toBe(true)
+    expect(snap1.has('val2')).toBe(true)
+    state.delete('val1')
+    const snap2 = snapshot(state)
+    expect(snap1.has('val1')).toBe(true)
+    expect(snap1.has('val2')).toBe(true)
+    expect(snap2.has('val1')).toBe(false)
+    expect(snap2.has('val2')).toBe(true)
+  })
+})