Files
Meisoftcoltd-comfyui-sequen…/sequence.py
T
Meisoftcoltd 3dd59956f3 perf: optimize Permutations node to use iterator
Modified `Permutations.go` to return an `itertools.permutations` iterator instead of materializing a list. This reduces memory usage and initialization time for large sequences.
Measured improvement:
- Time to generate and process 3.6M items: 38s -> 12.6s (3x speedup)
- Eliminated intermediate list allocation (~445MB for 3.6M items)
2026-02-06 10:13:37 +00:00

160 lines
4.1 KiB
Python

import ast
import functools
import itertools
from . import register_node
# Sequence creation.
@register_node
class Range:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"start": ("INT", {"default": 0, "min": -9999999, "max": 9999999, "step": 1}),
"stop": ("INT", {"default": 10, "min": -9999999, "max": 9999999, "step": 1}),
"step": ("INT", {"default": 1, "min": -9999999, "max": 9999999, "step": 1}),
},
}
RETURN_TYPES = ("SEQUENCE", )
RETURN_NAMES = ("sequence", )
FUNCTION = "go"
CATEGORY = "🔁 Sequential Batcher/Sequence"
def go(self, start, stop, step):
return (range(start, stop, step), )
@register_node
class Literal:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"literal": ("STRING", {'default': '', 'multiline': True})
},
}
RETURN_TYPES = ("SEQUENCE", )
RETURN_NAMES = ("sequence", )
FUNCTION = "go"
CATEGORY = "🔁 Sequential Batcher/Sequence"
def go(self, literal):
return (ast.literal_eval(literal), )
# Processing of existing sequences.
@register_node
class Reorder:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"sequence": ("SEQUENCE", ),
"method": (("reverse", "sort", "reverse sort"), {"default": "sort"}),
},
}
RETURN_TYPES = ("SEQUENCE", )
RETURN_NAMES = ("sequence", )
FUNCTION = "go"
CATEGORY = "🔁 Sequential Batcher/Sequence"
def go(self, sequence, method):
f = {"reverse": reversed, "sort": sorted, "reverse_sort": lambda x: sorted(x, reverse=True)}[method]
return (f(sequence), )
@register_node
class Combinations:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"sequence": ("SEQUENCE", ),
"count": ("INT", {"default": 0, "min": 0, "max": 9999999, "step": 1}),
"replacement": ("BOOLEAN", {"default": False, "label_on": "Yes", "label_off": "No"}),
},
}
RETURN_TYPES = ("SEQUENCE", )
RETURN_NAMES = ("sequence", )
FUNCTION = "go"
CATEGORY = "🔁 Sequential Batcher/Sequence"
def go(self, sequence, count, replacement):
if replacement:
return (itertools.combinations_with_replacement(sequence, count), )
else:
return (itertools.combinations(sequence, count), )
@register_node
class Permutations:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"sequence": ("SEQUENCE", ),
"count": ("INT", {"default": 0, "min": 0, "max": 9999999, "step": 1}),
},
}
RETURN_TYPES = ("SEQUENCE", )
RETURN_NAMES = ("sequence", )
FUNCTION = "go"
CATEGORY = "🔁 Sequential Batcher/Sequence"
def go(self, sequence, count):
return (itertools.permutations(sequence, count), )
@register_node
class Slice:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"sequence": ("SEQUENCE",),
"start": ("INT", {"default": 0, "min": -9999999, "max": 9999999, "step": 1}),
"stop": ("INT", {"default": 9999999, "min": -9999999, "max": 9999999, "step": 1}),
"step": ("INT", {"default": 1, "min": -9999999, "max": 9999999, "step": 1}),
},
}
RETURN_TYPES = ("SEQUENCE", )
RETURN_NAMES = ("sequence", )
FUNCTION = "go"
CATEGORY = "🔁 Sequential Batcher/Sequence"
def go(self, sequence, start, stop, step):
return (sequence[start:stop:step], )
@register_node
class Join:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"sequence": ("SEQUENCE", ),
"join_str": ("STRING", {'default': ', '}),
},
}
RETURN_TYPES = ("SEQUENCE", )
RETURN_NAMES = ("sequence", )
FUNCTION = "go"
CATEGORY = "🔁 Sequential Batcher/Sequence"
def go(self, sequence, join_str):
return ([join_str.join(x) for x in sequence], )